You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(97) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(127) |
Feb
(34) |
Mar
(16) |
Apr
(26) |
May
(55) |
Jun
(107) |
Jul
(36) |
Aug
(72) |
Sep
(90) |
Oct
(41) |
Nov
(27) |
Dec
(13) |
2008 |
Jan
(37) |
Feb
(39) |
Mar
(98) |
Apr
(115) |
May
(134) |
Jun
(120) |
Jul
(86) |
Aug
(149) |
Sep
(68) |
Oct
(66) |
Nov
(104) |
Dec
(49) |
2009 |
Jan
(131) |
Feb
(132) |
Mar
(125) |
Apr
(172) |
May
(161) |
Jun
(43) |
Jul
(47) |
Aug
(38) |
Sep
(18) |
Oct
(6) |
Nov
(1) |
Dec
(15) |
2010 |
Jan
(21) |
Feb
(8) |
Mar
(10) |
Apr
(4) |
May
(9) |
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
(2) |
Nov
|
Dec
(4) |
2011 |
Jan
(23) |
Feb
(10) |
Mar
(13) |
Apr
(3) |
May
|
Jun
(19) |
Jul
(11) |
Aug
(22) |
Sep
|
Oct
(4) |
Nov
(2) |
Dec
(12) |
2012 |
Jan
(3) |
Feb
(4) |
Mar
(7) |
Apr
(3) |
May
|
Jun
(1) |
Jul
(1) |
Aug
(30) |
Sep
(3) |
Oct
(2) |
Nov
|
Dec
(8) |
2013 |
Jan
(3) |
Feb
(40) |
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(12) |
Dec
|
2021 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
From: <ls...@us...> - 2007-01-07 18:42:16
|
Revision: 3044 http://jnode.svn.sourceforge.net/jnode/?rev=3044&view=rev Author: lsantha Date: 2007-01-07 10:42:15 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/javax/javax/security/sasl/Sasl.java trunk/core/src/classpath/javax/javax/security/sasl/SaslClientFactory.java trunk/core/src/classpath/javax/javax/security/sasl/SaslServerFactory.java trunk/core/src/classpath/javax/javax/swing/undo/CompoundEdit.java trunk/core/src/classpath/javax/javax/swing/undo/StateEdit.java trunk/core/src/classpath/javax/javax/swing/undo/StateEditable.java trunk/core/src/classpath/javax/javax/swing/undo/UndoableEditSupport.java Modified: trunk/core/src/classpath/javax/javax/security/sasl/Sasl.java =================================================================== --- trunk/core/src/classpath/javax/javax/security/sasl/Sasl.java 2007-01-07 18:41:27 UTC (rev 3043) +++ trunk/core/src/classpath/javax/javax/security/sasl/Sasl.java 2007-01-07 18:42:15 UTC (rev 3044) @@ -356,7 +356,8 @@ public static SaslClient createSaslClient(String[] mechanisms, String authorizationID, String protocol, - String serverName, Map props, + String serverName, + Map<String, ?> props, CallbackHandler cbh) throws SaslException { @@ -444,7 +445,7 @@ * {@link SaslClient} instance. * @see #createSaslClient(String[],String,String,String,Map,CallbackHandler) */ - public static Enumeration getSaslClientFactories() + public static Enumeration<SaslClientFactory> getSaslClientFactories() { Vector result = new Vector(); HashSet names = new HashSet(); @@ -559,7 +560,8 @@ */ public static SaslServer createSaslServer(String mechanism, String protocol, String serverName, - Map props, CallbackHandler cbh) + Map<String, ?> props, + CallbackHandler cbh) throws SaslException { if (mechanism == null) @@ -636,7 +638,7 @@ * {@link SaslServer} instance. * @see #createSaslServer(String,String,String,Map,CallbackHandler) */ - public static Enumeration getSaslServerFactories() + public static Enumeration<SaslServerFactory> getSaslServerFactories() { Vector result = new Vector(); HashSet names = new HashSet(); Modified: trunk/core/src/classpath/javax/javax/security/sasl/SaslClientFactory.java =================================================================== --- trunk/core/src/classpath/javax/javax/security/sasl/SaslClientFactory.java 2007-01-07 18:41:27 UTC (rev 3043) +++ trunk/core/src/classpath/javax/javax/security/sasl/SaslClientFactory.java 2007-01-07 18:42:15 UTC (rev 3044) @@ -97,8 +97,8 @@ * because of an error. */ SaslClient createSaslClient(String[] mechanisms, String authorizationID, - String protocol, String serverName, Map props, - CallbackHandler cbh) + String protocol, String serverName, + Map<String, ?> props, CallbackHandler cbh) throws SaslException; /** @@ -114,5 +114,5 @@ * properties, if present in props, are ignored. * @return a non-null array containing IANA-registered SASL mechanism names. */ - String[] getMechanismNames(Map props); + String[] getMechanismNames(Map<String, ?> props); } Modified: trunk/core/src/classpath/javax/javax/security/sasl/SaslServerFactory.java =================================================================== --- trunk/core/src/classpath/javax/javax/security/sasl/SaslServerFactory.java 2007-01-07 18:41:27 UTC (rev 3043) +++ trunk/core/src/classpath/javax/javax/security/sasl/SaslServerFactory.java 2007-01-07 18:42:15 UTC (rev 3044) @@ -95,7 +95,8 @@ * of an error. */ SaslServer createSaslServer(String mechanism, String protocol, - String serverName, Map props, CallbackHandler cbh) + String serverName, Map<String, ?> props, + CallbackHandler cbh) throws SaslException; /** @@ -111,5 +112,5 @@ * properties, if present in props, are ignored. * @return a non-null array containing IANA-registered SASL mechanism names. */ - String[] getMechanismNames(Map props); + String[] getMechanismNames(Map<String, ?> props); } Modified: trunk/core/src/classpath/javax/javax/swing/undo/CompoundEdit.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/undo/CompoundEdit.java 2007-01-07 18:41:27 UTC (rev 3043) +++ trunk/core/src/classpath/javax/javax/swing/undo/CompoundEdit.java 2007-01-07 18:42:15 UTC (rev 3044) @@ -1,5 +1,5 @@ /* CompoundEdit.java -- Combines multiple UndoableEdits. - Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -75,7 +75,7 @@ * The <code>UndoableEdit</code>s being combined into a compound * editing action. */ - protected Vector edits; + protected Vector<UndoableEdit> edits; /** @@ -92,7 +92,7 @@ */ public CompoundEdit() { - edits = new Vector(); + edits = new Vector<UndoableEdit>(); inProgress = true; } @@ -118,7 +118,7 @@ super.undo(); for (int i = edits.size() - 1; i >= 0; i--) - ((UndoableEdit) edits.elementAt(i)).undo(); + edits.elementAt(i).undo(); } @@ -143,7 +143,7 @@ super.redo(); for (int i = 0; i < edits.size(); i++) - ((UndoableEdit) edits.elementAt(i)).redo(); + edits.elementAt(i).redo(); } @@ -156,7 +156,7 @@ if (edits.size() == 0) return null; else - return (UndoableEdit) edits.elementAt(edits.size() - 1); + return edits.elementAt(edits.size() - 1); } @@ -172,7 +172,7 @@ public void die() { for (int i = edits.size() - 1; i >= 0; i--) - ((UndoableEdit) edits.elementAt(i)).die(); + edits.elementAt(i).die(); super.die(); } @@ -316,7 +316,7 @@ public boolean isSignificant() { for (int i = edits.size() - 1; i >= 0; i--) - if (((UndoableEdit) edits.elementAt(i)).isSignificant()) + if (edits.elementAt(i).isSignificant()) return true; return false; Modified: trunk/core/src/classpath/javax/javax/swing/undo/StateEdit.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/undo/StateEdit.java 2007-01-07 18:41:27 UTC (rev 3043) +++ trunk/core/src/classpath/javax/javax/swing/undo/StateEdit.java 2007-01-07 18:42:15 UTC (rev 3044) @@ -121,14 +121,14 @@ * The state of <code>object</code> at the time of constructing * this <code>StateEdit</code>. */ - protected Hashtable preState; + protected Hashtable<Object, Object> preState; /** * The state of <code>object</code> at the time when {@link #end()} * was called. */ - protected Hashtable postState; + protected Hashtable<Object, Object> postState; /** Modified: trunk/core/src/classpath/javax/javax/swing/undo/StateEditable.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/undo/StateEditable.java 2007-01-07 18:41:27 UTC (rev 3043) +++ trunk/core/src/classpath/javax/javax/swing/undo/StateEditable.java 2007-01-07 18:42:15 UTC (rev 3044) @@ -100,7 +100,7 @@ * @param state a hash table containing the relevant state * information. */ - void restoreState(Hashtable state); + void restoreState(Hashtable<?, ?> state); /** @@ -110,5 +110,5 @@ * @param state a hash table for storing relevant state * information. */ - void storeState(Hashtable state); + void storeState(Hashtable<Object, Object> state); } Modified: trunk/core/src/classpath/javax/javax/swing/undo/UndoableEditSupport.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/undo/UndoableEditSupport.java 2007-01-07 18:41:27 UTC (rev 3043) +++ trunk/core/src/classpath/javax/javax/swing/undo/UndoableEditSupport.java 2007-01-07 18:42:15 UTC (rev 3044) @@ -69,7 +69,8 @@ /** * The currently registered listeners. */ - protected Vector listeners = new Vector(); + protected Vector<UndoableEditListener> listeners = + new Vector<UndoableEditListener>(); /** @@ -148,7 +149,7 @@ public synchronized UndoableEditListener[] getUndoableEditListeners() { UndoableEditListener[] result = new UndoableEditListener[listeners.size()]; - return (UndoableEditListener[]) listeners.toArray(result); + return listeners.toArray(result); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-07 18:41:28
|
Revision: 3043 http://jnode.svn.sourceforge.net/jnode/?rev=3043&view=rev Author: lsantha Date: 2007-01-07 10:41:27 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/awt/AWTEvent.java trunk/core/src/classpath/java/java/awt/AWTEventMulticaster.java trunk/core/src/classpath/java/java/awt/AWTKeyStroke.java trunk/core/src/classpath/java/java/awt/BasicStroke.java trunk/core/src/classpath/java/java/awt/CardLayout.java trunk/core/src/classpath/java/java/awt/FileDialog.java trunk/core/src/classpath/java/java/awt/FlowLayout.java trunk/core/src/classpath/java/java/awt/GridBagLayout.java trunk/core/src/classpath/java/java/awt/GridLayout.java trunk/core/src/classpath/java/java/awt/datatransfer/DataFlavor.java trunk/core/src/classpath/java/java/awt/datatransfer/FlavorMap.java trunk/core/src/classpath/java/java/awt/datatransfer/FlavorTable.java trunk/core/src/classpath/java/java/awt/datatransfer/SystemFlavorMap.java trunk/core/src/classpath/java/java/awt/event/ComponentEvent.java trunk/core/src/classpath/java/java/awt/font/LineBreakMeasurer.java trunk/core/src/classpath/java/java/awt/font/TextHitInfo.java trunk/core/src/classpath/java/java/awt/font/TextLayout.java trunk/core/src/classpath/java/java/awt/font/TextMeasurer.java trunk/core/src/classpath/java/java/awt/geom/Arc2D.java trunk/core/src/classpath/java/java/awt/geom/GeneralPath.java trunk/core/src/classpath/java/java/awt/geom/RectangularShape.java trunk/core/src/classpath/java/java/awt/geom/RoundRectangle2D.java trunk/core/src/classpath/java/java/awt/print/PrinterJob.java trunk/core/src/classpath/java/java/lang/Package.java trunk/core/src/classpath/java/java/lang/Void.java trunk/core/src/classpath/java/java/math/BigDecimal.java trunk/core/src/classpath/java/java/math/BigInteger.java trunk/core/src/classpath/java/java/math/MathContext.java trunk/core/src/classpath/java/java/net/MimeTypeMapper.java trunk/core/src/classpath/java/java/nio/channels/Channel.java trunk/core/src/classpath/java/java/nio/channels/Selector.java trunk/core/src/classpath/java/java/nio/channels/spi/AbstractSelectableChannel.java trunk/core/src/classpath/java/java/nio/channels/spi/AbstractSelector.java trunk/core/src/classpath/java/java/nio/charset/Charset.java trunk/core/src/classpath/java/java/nio/charset/spi/CharsetProvider.java trunk/core/src/classpath/java/java/security/AlgorithmParametersSpi.java trunk/core/src/classpath/java/java/security/BasicPermission.java trunk/core/src/classpath/java/java/security/IdentityScope.java trunk/core/src/classpath/java/java/security/KeyFactorySpi.java trunk/core/src/classpath/java/java/security/KeyStoreSpi.java trunk/core/src/classpath/java/java/security/PermissionCollection.java trunk/core/src/classpath/java/java/security/Permissions.java trunk/core/src/classpath/java/java/security/Security.java trunk/core/src/classpath/java/java/util/jar/Attributes.java trunk/core/src/classpath/java/java/util/jar/JarEntry.java trunk/core/src/classpath/java/java/util/jar/JarFile.java trunk/core/src/classpath/java/java/util/jar/Manifest.java trunk/core/src/classpath/java/java/util/regex/Matcher.java trunk/core/src/classpath/java/java/util/regex/Pattern.java trunk/core/src/classpath/java/java/util/zip/DeflaterEngine.java trunk/core/src/classpath/java/java/util/zip/Inflater.java trunk/core/src/classpath/java/java/util/zip/ZipFile.java trunk/core/src/classpath/java/java/util/zip/ZipInputStream.java Modified: trunk/core/src/classpath/java/java/awt/AWTEvent.java =================================================================== --- trunk/core/src/classpath/java/java/awt/AWTEvent.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/AWTEvent.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -262,9 +262,17 @@ */ public String toString () { + String src; + if (source instanceof Component) + src = ((Component) source).getName(); + else if (source instanceof MenuComponent) + src = ((MenuComponent) source).getName(); + else if (source != null) + src = source.toString(); + else + src = "null"; String string = getClass ().getName () + "[" + paramString () + "] on " - + source; - + + src; return string; } Modified: trunk/core/src/classpath/java/java/awt/AWTEventMulticaster.java =================================================================== --- trunk/core/src/classpath/java/java/awt/AWTEventMulticaster.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/AWTEventMulticaster.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -1175,16 +1175,17 @@ * @throws IllegalArgumentException if type is Void.TYPE * @since 1.4 */ - public static EventListener[] getListeners(EventListener l, Class type) + public static <T extends EventListener> T[] getListeners(EventListener l, + Class<T> type) { - ArrayList list = new ArrayList(); + ArrayList<EventListener> list = new ArrayList<EventListener>(); if (l instanceof AWTEventMulticaster) ((AWTEventMulticaster) l).getListeners(list, type); else if (type.isInstance(l)) list.add(l); EventListener[] r = (EventListener[]) Array.newInstance(type, list.size()); list.toArray(r); - return r; + return (T[]) r; } /** Modified: trunk/core/src/classpath/java/java/awt/AWTKeyStroke.java =================================================================== --- trunk/core/src/classpath/java/java/awt/AWTKeyStroke.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/AWTKeyStroke.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -1,5 +1,5 @@ /* AWTKeyStroke.java -- an immutable key stroke - Copyright (C) 2002, 2004, 2005 Free Software Foundation + Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation This file is part of GNU Classpath. @@ -65,6 +65,7 @@ * no-arg constructor (of any accessibility). * * @author Eric Blake (eb...@em...) + * @author Andrew John Hughes (gnu...@me...) * @see #getAWTKeyStroke(char) * @since 1.4 * @status updated to 1.4 @@ -85,14 +86,16 @@ * under the assumption that garbage collection of a new keystroke is * easy when we find the old one that it matches in the cache. */ - private static final LinkedHashMap cache = new LinkedHashMap(11, 0.75f, true) + private static final LinkedHashMap<AWTKeyStroke,AWTKeyStroke> cache = + new LinkedHashMap<AWTKeyStroke,AWTKeyStroke>(11, 0.75f, true) { /** The largest the keystroke cache can grow. */ private static final int MAX_CACHE_SIZE = 2048; /** Prune stale entries. */ - protected boolean removeEldestEntry(Map.Entry eldest) - { // XXX - FIXME Use Map.Entry, not just Entry as gcj 3.1 workaround. + protected boolean removeEldestEntry(Entry<AWTKeyStroke,AWTKeyStroke> + eldest) + { return size() > MAX_CACHE_SIZE; } }; @@ -114,7 +117,7 @@ * * @see #getAWTKeyStroke(String) */ - static final HashMap vktable = new HashMap(); + static final HashMap<String,Object> vktable = new HashMap<String,Object>(); static { // Using reflection saves the hassle of keeping this in sync with KeyEvent, @@ -229,7 +232,7 @@ * @throws IllegalArgumentException subclass doesn't have no-arg constructor * @throws ClassCastException subclass doesn't extend AWTKeyStroke */ - protected static void registerSubclass(final Class subclass) + protected static void registerSubclass(final Class<?> subclass) { if (subclass == null) throw new IllegalArgumentException(); @@ -252,7 +255,8 @@ throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { - Constructor c = subclass.getDeclaredConstructor(null); + Constructor<?> c = + subclass.getDeclaredConstructor((Class<?>[])null); c.setAccessible(true); // Create a new instance, to make sure that we can, and // to cause any ClassCastException. @@ -595,7 +599,7 @@ */ protected Object readResolve() throws ObjectStreamException { - AWTKeyStroke s = (AWTKeyStroke) cache.get(this); + AWTKeyStroke s = cache.get(this); if (s != null) return s; cache.put(this, this); Modified: trunk/core/src/classpath/java/java/awt/BasicStroke.java =================================================================== --- trunk/core/src/classpath/java/java/awt/BasicStroke.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/BasicStroke.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -761,9 +761,13 @@ p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()}; dx = p1[0] - p0[0]; dy = p1[1] - p0[1]; + if (dx != 0 && dy != 0) + { l = Math.sqrt(dx * dx + dy * dy); dx = (2.0/3.0)*width*dx/l; dy = (2.0/3.0)*width*dy/l; + } + c1 = new Point2D.Double(p1[0] + dx, p1[1] + dy); c2 = new Point2D.Double(b.P1.getX() + dx, b.P1.getY() + dy); a.add(new CubicSegment(a.last.P2, c1, c2, b.P1)); Modified: trunk/core/src/classpath/java/java/awt/CardLayout.java =================================================================== --- trunk/core/src/classpath/java/java/awt/CardLayout.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/CardLayout.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -225,6 +225,8 @@ */ public Dimension maximumLayoutSize (Container target) { + if (target == null || target.ncomponents == 0) + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); // The JCL says that this returns Integer.MAX_VALUE for both // dimensions. But that just seems wrong to me. return getSize (target, MAX); @@ -350,6 +352,7 @@ } } ((Component) target).setVisible (true); + parent.validate(); } } @@ -360,7 +363,7 @@ */ public String toString () { - return getClass ().getName () + "[" + hgap + "," + vgap + "]"; + return getClass ().getName () + "[hgap=" + hgap + ",vgap=" + vgap + "]"; } /** @@ -400,11 +403,11 @@ { if (comps[i].isVisible ()) { - if (what == NEXT) + if (choice == i) { - choice = i + 1; - if (choice == num) - choice = 0; + // Do nothing if we're already looking at the right + // component. + return; } else if (what == PREV) { @@ -412,16 +415,19 @@ if (choice < 0) choice = num - 1; } - else if (choice == i) + else if (what == NEXT) { - // Do nothing if we're already looking at the right - // component. - return; + choice = i + 1; + if (choice == num) + choice = 0; } comps[i].setVisible (false); if (choice >= 0) break; + } else + { + comps[i].setVisible(true); } } Modified: trunk/core/src/classpath/java/java/awt/FileDialog.java =================================================================== --- trunk/core/src/classpath/java/java/awt/FileDialog.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/FileDialog.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -95,6 +95,11 @@ */ private int mode; +/** + * The number used to generate the name returned by getName. + */ +private static transient long next_file_dialog_number; + /*************************************************************************/ /* @@ -300,7 +305,11 @@ public synchronized void setFile(String file) { + if ("".equals(file)) + this.file = null; + else this.file = file; + if (peer != null) { FileDialogPeer f = (FileDialogPeer) peer; @@ -366,5 +375,22 @@ ",mode=" + mode + "," + super.paramString()); } +/** + * Generate a unique name for this <code>FileDialog</code>. + * + * @return A unique name for this <code>FileDialog</code>. + */ +String +generateName() +{ + return "filedlg" + getUniqueLong(); +} + +private static synchronized long +getUniqueLong() +{ + return next_file_dialog_number++; +} + } // class FileDialog Modified: trunk/core/src/classpath/java/java/awt/FlowLayout.java =================================================================== --- trunk/core/src/classpath/java/java/awt/FlowLayout.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/FlowLayout.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -337,6 +337,9 @@ Insets ins = parent.getInsets (); + if (num == 0) + w += 2 * hgap + ins.left + ins.right; + else w += (num + 1) * hgap + ins.left + ins.right; h += 2 * vgap + ins.top + ins.bottom; Modified: trunk/core/src/classpath/java/java/awt/GridBagLayout.java =================================================================== --- trunk/core/src/classpath/java/java/awt/GridBagLayout.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/GridBagLayout.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -1,5 +1,5 @@ /* GridBagLayout - Layout manager for components according to GridBagConstraints - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,8 +38,6 @@ package java.awt; -import gnu.classpath.NotImplementedException; - import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; @@ -48,6 +46,7 @@ /** * @author Michael Koch (kon...@gm...) * @author Jeroen Frijters (je...@fr...) + * @author Andrew John Hughes (gnu...@me...) */ public class GridBagLayout implements Serializable, LayoutManager2 @@ -64,8 +63,8 @@ // REMAINDER constraints. // Constraints kept in comptable are never modified, and constraints // kept in internalcomptable can be modified internally only. - protected Hashtable comptable; - private Hashtable internalcomptable; + protected Hashtable<Component,GridBagConstraints> comptable; + private Hashtable<Component,GridBagConstraints> internalcomptable; protected GridBagLayoutInfo layoutInfo; protected GridBagConstraints defaultConstraints; @@ -76,8 +75,8 @@ public GridBagLayout () { - this.comptable = new Hashtable(); - this.internalcomptable = new Hashtable(); + this.comptable = new Hashtable<Component,GridBagConstraints>(); + this.internalcomptable = new Hashtable<Component,GridBagConstraints>(); this.defaultConstraints= new GridBagConstraints(); } @@ -322,14 +321,35 @@ } /** - * Obsolete. + * Return a string representation of this GridBagLayout. + * + * @return a string representation */ - protected void AdjustForGravity (GridBagConstraints gbc, Rectangle rect) - throws NotImplementedException + public String toString() { - // FIXME - throw new Error ("Not implemented"); + return getClass().getName(); } + + /** + * Move and resize a rectangle according to a set of grid bag + * constraints. The x, y, width and height fields of the + * rectangle argument are adjusted to the new values. + * + * @param constraints position and size constraints + * @param r rectangle to be moved and resized + */ + protected void AdjustForGravity (GridBagConstraints constraints, + Rectangle r) + { + Insets insets = constraints.insets; + if (insets != null) + { + r.x += insets.left; + r.y += insets.top; + r.width -= insets.left + insets.right; + r.height -= insets.top + insets.bottom; + } + } /** * Obsolete. @@ -353,10 +373,9 @@ // layoutInfo. So we wait until after this for loop to set // layoutInfo. Component lastComp = null; - int cellx = 0; - int celly = 0; - int cellw = 0; - int cellh = 0; + + Rectangle cell = new Rectangle(); + for (int i = 0; i < components.length; i++) { Component component = components[i]; @@ -370,29 +389,23 @@ if (lastComp != null && constraints.gridheight == GridBagConstraints.REMAINDER) - celly += cellh; + cell.y += cell.height; else - celly = sumIntArray(info.rowHeights, constraints.gridy); + cell.y = sumIntArray(info.rowHeights, constraints.gridy); if (lastComp != null && constraints.gridwidth == GridBagConstraints.REMAINDER) - cellx += cellw; + cell.x += cell.width; else - cellx = sumIntArray(info.colWidths, constraints.gridx); + cell.x = sumIntArray(info.colWidths, constraints.gridx); - cellw = sumIntArray(info.colWidths, constraints.gridx - + constraints.gridwidth) - cellx; - cellh = sumIntArray(info.rowHeights, constraints.gridy - + constraints.gridheight) - celly; + cell.width = sumIntArray(info.colWidths, constraints.gridx + + constraints.gridwidth) - cell.x; + cell.height = sumIntArray(info.rowHeights, constraints.gridy + + constraints.gridheight) - cell.y; - Insets insets = constraints.insets; - if (insets != null) - { - cellx += insets.left; - celly += insets.top; - cellw -= insets.left + insets.right; - cellh -= insets.top + insets.bottom; - } + // Adjust for insets. + AdjustForGravity( constraints, cell ); // Note: Documentation says that padding is added on both sides, but // visual inspection shows that the Sun implementation only adds it @@ -403,14 +416,14 @@ switch (constraints.fill) { case GridBagConstraints.HORIZONTAL: - dim.width = cellw; + dim.width = cell.width; break; case GridBagConstraints.VERTICAL: - dim.height = cellh; + dim.height = cell.height; break; case GridBagConstraints.BOTH: - dim.width = cellw; - dim.height = cellh; + dim.width = cell.width; + dim.height = cell.height; break; } @@ -420,40 +433,40 @@ switch (constraints.anchor) { case GridBagConstraints.NORTH: - x = cellx + (cellw - dim.width) / 2; - y = celly; + x = cell.x + (cell.width - dim.width) / 2; + y = cell.y; break; case GridBagConstraints.SOUTH: - x = cellx + (cellw - dim.width) / 2; - y = celly + cellh - dim.height; + x = cell.x + (cell.width - dim.width) / 2; + y = cell.y + cell.height - dim.height; break; case GridBagConstraints.WEST: - x = cellx; - y = celly + (cellh - dim.height) / 2; + x = cell.x; + y = cell.y + (cell.height - dim.height) / 2; break; case GridBagConstraints.EAST: - x = cellx + cellw - dim.width; - y = celly + (cellh - dim.height) / 2; + x = cell.x + cell.width - dim.width; + y = cell.y + (cell.height - dim.height) / 2; break; case GridBagConstraints.NORTHEAST: - x = cellx + cellw - dim.width; - y = celly; + x = cell.x + cell.width - dim.width; + y = cell.y; break; case GridBagConstraints.NORTHWEST: - x = cellx; - y = celly; + x = cell.x; + y = cell.y; break; case GridBagConstraints.SOUTHEAST: - x = cellx + cellw - dim.width; - y = celly + cellh - dim.height; + x = cell.x + cell.width - dim.width; + y = cell.y + cell.height - dim.height; break; case GridBagConstraints.SOUTHWEST: - x = cellx; - y = celly + cellh - dim.height; + x = cell.x; + y = cell.y + cell.height - dim.height; break; default: - x = cellx + (cellw - dim.width) / 2; - y = celly + (cellh - dim.height) / 2; + x = cell.x + (cell.width - dim.width) / 2; + y = cell.y + (cell.height - dim.height) / 2; break; } component.setBounds(info.pos_x + x, info.pos_y + y, dim.width, @@ -487,16 +500,18 @@ // Guaranteed to contain the last component added to the given row // or column, whose gridwidth/height is not REMAINDER. - HashMap lastInRow = new HashMap(); - HashMap lastInCol = new HashMap(); + HashMap<Integer,Component> lastInRow = new HashMap<Integer,Component>(); + HashMap<Integer,Component> lastInCol = new HashMap<Integer,Component>(); Component[] components = parent.getComponents(); // Components sorted by gridwidths/heights, // smallest to largest, with REMAINDER and RELATIVE at the end. // These are useful when determining sizes and weights. - ArrayList sortedByWidth = new ArrayList(components.length); - ArrayList sortedByHeight = new ArrayList(components.length); + ArrayList<Component> sortedByWidth = + new ArrayList<Component>(components.length); + ArrayList<Component> sortedByHeight = + new ArrayList<Component>(components.length); // STEP 1: first we figure out how many rows/columns for (int i = 0; i < components.length; i++) @@ -761,7 +776,7 @@ // STEP 3: Determine sizes and weights for columns. for (int i = 0; i < sortedByWidth.size(); i++) { - Component component = (Component) sortedByWidth.get(i); + Component component = sortedByWidth.get(i); // If component is not visible we dont have to care about it. if (!component.isVisible()) @@ -875,7 +890,8 @@ * width. Otherwise, sort by height. * FIXME: Use a better sorting algorithm. */ - private void sortBySpan (Component component, int span, ArrayList list, boolean sortByWidth) + private void sortBySpan (Component component, int span, + ArrayList<Component> list, boolean sortByWidth) { if (span == GridBagConstraints.REMAINDER || span == GridBagConstraints.RELATIVE) @@ -1082,10 +1098,18 @@ } /** + * Move and resize a rectangle according to a set of grid bag + * constraints. The x, y, width and height fields of the + * rectangle argument are adjusted to the new values. + * + * @param constraints position and size constraints + * @param r rectangle to be moved and resized + * * @since 1.4 */ - protected void adjustForGravity (GridBagConstraints gbc, Rectangle rect) + protected void adjustForGravity (GridBagConstraints constraints, + Rectangle r) { - AdjustForGravity (gbc, rect); + AdjustForGravity (constraints, r); } } Modified: trunk/core/src/classpath/java/java/awt/GridLayout.java =================================================================== --- trunk/core/src/classpath/java/java/awt/GridLayout.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/GridLayout.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -289,7 +289,7 @@ public String toString () { return (getClass ().getName () + "[" - + ",hgap=" + hgap + ",vgap=" + vgap + + "hgap=" + hgap + ",vgap=" + vgap + ",rows=" + rows + ",cols=" + cols + "]"); } Modified: trunk/core/src/classpath/java/java/awt/datatransfer/DataFlavor.java =================================================================== --- trunk/core/src/classpath/java/java/awt/datatransfer/DataFlavor.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/datatransfer/DataFlavor.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -38,14 +38,13 @@ package java.awt.datatransfer; -import gnu.classpath.NotImplementedException; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectInput; import java.io.ObjectOutput; +import java.io.OptionalDataException; import java.io.Reader; import java.io.Serializable; import java.io.StringReader; @@ -76,8 +75,7 @@ * deals with bytes not chars. Use <code>getRederForText()</code>. */ public static final DataFlavor plainTextFlavor = - new DataFlavor(java.io.InputStream.class, - "text/plain; charset=unicode", + new DataFlavor("text/plain; charset=unicode; class=java.io.InputStream", "plain unicode text"); /** @@ -94,8 +92,7 @@ * element of the list being a <code>java.io.File</code>. */ public static final DataFlavor javaFileListFlavor = - new DataFlavor(java.util.List.class, - "application/x-java-file-list; class=java.util.List", + new DataFlavor("application/x-java-file-list; class=java.util.List", "Java File List"); /** @@ -132,10 +129,10 @@ */ // The MIME type for this flavor - private final String mimeType; + private MimeType mimeType; // The representation class for this flavor - private final Class representationClass; + private Class<?> representationClass; // The human readable name of this flavor private String humanPresentableName; @@ -156,7 +153,7 @@ * * @exception ClassNotFoundException If the class cannot be loaded. */ - protected static final Class tryToLoadClass(String className, + protected static final Class<?> tryToLoadClass(String className, ClassLoader classLoader) throws ClassNotFoundException { @@ -198,63 +195,7 @@ throw new ClassNotFoundException(className); } - private static Class getRepresentationClassFromMimeThrows(String mimeString, - ClassLoader classLoader) - throws ClassNotFoundException - { - String classname = getParameter("class", mimeString); - if (classname != null) - return tryToLoadClass(classname, classLoader); - else - return java.io.InputStream.class; - } - - // Same as above, but wraps any ClassNotFoundExceptions - private static Class getRepresentationClassFromMime(String mimeString, - ClassLoader classLoader) - { - try - { - return getRepresentationClassFromMimeThrows(mimeString, classLoader); - } - catch(ClassNotFoundException cnfe) - { - IllegalArgumentException iae; - iae = new IllegalArgumentException("mimeString: " - + mimeString - + " classLoader: " - + classLoader); - iae.initCause(cnfe); - throw iae; - } - } - /** - * Returns the value of the named MIME type parameter, or <code>null</code> - * if the parameter does not exist. Given the parameter name and the mime - * string. - * - * @param paramName The name of the parameter. - * @param mimeString The mime string from where the name should be found. - * - * @return The value of the parameter or null. - */ - private static String getParameter(String paramName, String mimeString) - { - int idx = mimeString.indexOf(paramName + "="); - if (idx == -1) - return(null); - - String value = mimeString.substring(idx + paramName.length() + 1); - - idx = value.indexOf(";"); - if (idx == -1) - return(value); - else - return(value.substring(0, idx)); - } - - /** * XXX - Currently returns <code>plainTextFlavor</code>. */ public static final DataFlavor getTextPlainUnicodeFlavor() @@ -321,35 +262,10 @@ */ public DataFlavor() { - mimeType = null; - representationClass = null; - humanPresentableName = null; + // Used for deserialization only, nothing to do here. } /** - * Private constructor. - */ - private DataFlavor(Class representationClass, - String mimeType, - String humanPresentableName) - { - this.representationClass = representationClass; - this.mimeType = mimeType; - - // Do some simple validity checks - String type = getPrimaryType() + "/" + getSubType(); - if (type.indexOf(' ') != -1 - || type.indexOf('=') != -1 - || type.indexOf(';') != -1) - throw new IllegalArgumentException(mimeType); - - if (humanPresentableName != null) - this.humanPresentableName = humanPresentableName; - else - this.humanPresentableName = mimeType; - } - - /** * Initializes a new instance of <code>DataFlavor</code>. The class * and human readable name are specified, the MIME type will be * "application/x-java-serialized-object". If the human readable name @@ -359,13 +275,23 @@ * @param representationClass The representation class for this object. * @param humanPresentableName The display name of the object. */ - public DataFlavor(Class representationClass, String humanPresentableName) + public DataFlavor(Class<?> representationClass, String humanPresentableName) { - this(representationClass, - "application/x-java-serialized-object" - + "; class=" - + representationClass.getName(), - humanPresentableName); + if (representationClass == null) + throw new NullPointerException("representationClass must not be null"); + try + { + mimeType = new MimeType(javaSerializedObjectMimeType); + } + catch (MimeTypeParseException ex) + { + // Must not happen as we use a constant string. + assert false; + } + if (humanPresentableName == null) + humanPresentableName = javaSerializedObjectMimeType; + this.humanPresentableName = humanPresentableName; + this.representationClass = representationClass; } /** @@ -390,8 +316,7 @@ ClassLoader classLoader) throws ClassNotFoundException { - this(getRepresentationClassFromMimeThrows(mimeType, classLoader), - mimeType, humanPresentableName); + init(mimeType, humanPresentableName, classLoader); } /** @@ -412,8 +337,17 @@ */ public DataFlavor(String mimeType, String humanPresentableName) { - this(getRepresentationClassFromMime (mimeType, null), - mimeType, humanPresentableName); + try + { + init(mimeType, humanPresentableName, getClass().getClassLoader()); + } + catch (ClassNotFoundException ex) + { + IllegalArgumentException iae = + new IllegalArgumentException("Class not found: " + ex.getMessage()); + iae.initCause(ex); + throw iae; + } } /** @@ -432,18 +366,64 @@ */ public DataFlavor(String mimeType) throws ClassNotFoundException { - this(getRepresentationClassFromMimeThrows(mimeType, null), - mimeType, null); + init(mimeType, null, getClass().getClassLoader()); } /** + * Called by various constructors to initialize this object. + * + * @param mime the mime string + * @param humanPresentableName the human presentable name + * @param loader the class loader to use for loading the representation + * class + */ + private void init(String mime, String humanPresentableName, + ClassLoader loader) + throws ClassNotFoundException + { + if (mime == null) + throw new NullPointerException("The mime type must not be null"); + try + { + mimeType = new MimeType(mime); + } + catch (MimeTypeParseException ex) + { + IllegalArgumentException iae = + new IllegalArgumentException("Invalid mime type"); + iae.initCause(ex); + throw iae; + } + String className = mimeType.getParameter("class"); + if (className == null) + { + if (mimeType.getBaseType().equals(javaSerializedObjectMimeType)) + throw new IllegalArgumentException("Serialized object type must have" + + " a representation class parameter"); + else + representationClass = java.io.InputStream.class; + } + else + representationClass = tryToLoadClass(className, loader); + mimeType.addParameter("class", representationClass.getName()); + + if (humanPresentableName == null) + { + humanPresentableName = mimeType.getParameter("humanPresentableName"); + if (humanPresentableName == null) + humanPresentableName = mimeType.getBaseType(); + } + this.humanPresentableName = humanPresentableName; + } + + /** * Returns the MIME type of this flavor. * * @return The MIME type for this flavor. */ public String getMimeType() { - return(mimeType); + return(mimeType.toString()); } /** @@ -451,7 +431,7 @@ * * @return The representation class for this flavor. */ - public Class getRepresentationClass() + public Class<?> getRepresentationClass() { return(representationClass); } @@ -473,11 +453,7 @@ */ public String getPrimaryType() { - int idx = mimeType.indexOf("/"); - if (idx == -1) - return(mimeType); - - return(mimeType.substring(0, idx)); + return(mimeType.getPrimaryType()); } /** @@ -487,15 +463,7 @@ */ public String getSubType() { - int start = mimeType.indexOf("/"); - if (start == -1) - return ""; - - int end = mimeType.indexOf(";", start + 1); - if (end == -1) - return mimeType.substring(start + 1); - else - return mimeType.substring(start + 1, end); + return mimeType.getSubType(); } /** @@ -511,7 +479,7 @@ if ("humanPresentableName".equals(paramName)) return getHumanPresentableName(); - return getParameter(paramName, mimeType); + return mimeType.getParameter(paramName); } /** @@ -537,16 +505,22 @@ */ public boolean isMimeTypeEqual(String mimeType) { - String mime = getMimeType(); - int i = mime.indexOf(";"); - if (i != -1) - mime = mime.substring(0, i); - - i = mimeType.indexOf(";"); - if (i != -1) - mimeType = mimeType.substring(0, i); - - return mime.equals(mimeType); + if (mimeType == null) + throw new NullPointerException("mimeType must not be null"); + boolean equal = false; + try + { + if (this.mimeType != null) + { + MimeType other = new MimeType(mimeType); + equal = this.mimeType.matches(other); + } + } + catch (MimeTypeParseException ex) + { + // Return false in this case. + } + return equal; } /** @@ -571,7 +545,7 @@ */ public boolean isMimeTypeSerializedObject() { - return mimeType.startsWith(javaSerializedObjectMimeType); + return isMimeTypeEqual(javaSerializedObjectMimeType); } /** @@ -617,8 +591,8 @@ */ public boolean isFlavorSerializedObjectType() { - // FIXME: What is the diff between this and isMimeTypeSerializedObject? - return(mimeType.startsWith(javaSerializedObjectMimeType)); + return isRepresentationClassSerializable() + && isMimeTypeEqual(javaSerializedObjectMimeType); } /** @@ -629,7 +603,9 @@ */ public boolean isFlavorRemoteObjectType() { - return(mimeType.startsWith(javaRemoteObjectMimeType)); + return isRepresentationClassRemote() + && isRepresentationClassSerializable() + && isMimeTypeEqual(javaRemoteObjectMimeType); } /** @@ -770,7 +746,7 @@ */ public int hashCode() { - return mimeType.toLowerCase().hashCode() ^ representationClass.hashCode(); + return mimeType.toString().hashCode() ^ representationClass.hashCode(); } /** @@ -822,9 +798,17 @@ * @exception IOException If an error occurs. */ public void writeExternal(ObjectOutput stream) - throws IOException, NotImplementedException + throws IOException { - // FIXME: Implement me + if (mimeType != null) + { + mimeType.addParameter("humanPresentableName", humanPresentableName); + stream.writeObject(mimeType); + mimeType.removeParameter("humanPresentableName"); + } + else + stream.writeObject(null); + stream.writeObject(representationClass); } @@ -838,9 +822,34 @@ * cannot be found. */ public void readExternal(ObjectInput stream) - throws IOException, ClassNotFoundException, NotImplementedException + throws IOException, ClassNotFoundException { - // FIXME: Implement me + mimeType = (MimeType) stream.readObject(); + String className = null; + if (mimeType != null) + { + humanPresentableName = + mimeType.getParameter("humanPresentableName"); + mimeType.removeParameter("humanPresentableName"); + className = mimeType.getParameter("class"); + if (className == null) + throw new IOException("No class in mime type"); + } + try + { + representationClass = (Class) stream.readObject(); + } + catch (OptionalDataException ex) + { + if (ex.eof && ex.length == 0) + { + if (className != null) + representationClass = tryToLoadClass(className, + getClass().getClassLoader()); + } + else + throw ex; + } } /** @@ -861,7 +870,7 @@ * * @since 1.3 */ - public final Class getDefaultRepresentationClass() + public final Class<?> getDefaultRepresentationClass() { return java.io.InputStream.class; } Modified: trunk/core/src/classpath/java/java/awt/datatransfer/FlavorMap.java =================================================================== --- trunk/core/src/classpath/java/java/awt/datatransfer/FlavorMap.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/datatransfer/FlavorMap.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -58,7 +58,7 @@ * * @return A <code>Map</code> of native data types. */ - Map getNativesForFlavors (DataFlavor[] flavors); + Map<DataFlavor, String> getNativesForFlavors (DataFlavor[] flavors); /** * Maps the specified native type names to <code>DataFlavor</code>'s. @@ -71,5 +71,5 @@ * * @return A <code>Map</code> of data flavors. */ - Map getFlavorsForNatives (String[] natives); + Map<String, DataFlavor> getFlavorsForNatives (String[] natives); } Modified: trunk/core/src/classpath/java/java/awt/datatransfer/FlavorTable.java =================================================================== --- trunk/core/src/classpath/java/java/awt/datatransfer/FlavorTable.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/datatransfer/FlavorTable.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -59,7 +59,7 @@ * @param flavor the flavor to look up, or null to return all natives * @return the sorted list of natives */ - List getNativesForFlavor(DataFlavor flavor); + List<String> getNativesForFlavor(DataFlavor flavor); /** * Returns a list of flavors corresponding to the given String native. The @@ -69,5 +69,5 @@ * @param name the native name to look up, or null to return all flavors * @return the sorted list of flavors */ - List getFlavorsForNative(String name); + List<DataFlavor> getFlavorsForNative(String name); } Modified: trunk/core/src/classpath/java/java/awt/datatransfer/SystemFlavorMap.java =================================================================== --- trunk/core/src/classpath/java/java/awt/datatransfer/SystemFlavorMap.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/datatransfer/SystemFlavorMap.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -38,12 +38,21 @@ package java.awt.datatransfer; -import gnu.classpath.NotImplementedException; - +import java.awt.Toolkit; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.WeakHashMap; /** @@ -72,22 +81,105 @@ * This map maps native <code>String</code>s to lists of * <code>DataFlavor</code>s */ - private HashMap nativeToFlavorMap = new HashMap(); + private HashMap<String,List<DataFlavor>> nativeToFlavorMap = + new HashMap<String,List<DataFlavor>>(); /** * This map maps <code>DataFlavor</code>s to lists of native * <code>String</code>s */ - private HashMap flavorToNativeMap = new HashMap(); + private HashMap<DataFlavor, List<String>> flavorToNativeMap = + new HashMap<DataFlavor, List<String>>(); /** * Private constructor. */ private SystemFlavorMap () { + AccessController.doPrivileged + (new PrivilegedAction<Object>() + { + public Object run() + { + try + { + // Load installed flavormap.properties first. + String sep = File.separator; + File propsFile = + new File(System.getProperty("gnu.classpath.home.url") + + sep + "accessibility.properties"); + InputStream in = new FileInputStream(propsFile); + Properties props = new Properties(); + props.load(in); + in.close(); + + String augmented = Toolkit.getProperty("AWT.DnD.flavorMapFileURL", + null); + if (augmented != null) + { + URL url = new URL(augmented); + in = url.openStream(); + props.load(in); + } + setupMapping(props); + } + catch (IOException ex) + { + // Can't do anything about it. + } + return null; + } + }); } /** + * Sets up the mapping from native to mime types and vice versa as specified + * in the flavormap.properties file. + * + * This is package private to avoid an accessor method. + * + * @param props the properties file + */ + void setupMapping(Properties props) + { + Enumeration propNames = props.propertyNames(); + while (propNames.hasMoreElements()) + { + try + { + String nat = (String) propNames.nextElement(); + String mime = (String) props.getProperty(nat); + // Check valid mime type. + MimeType type = new MimeType(mime); + DataFlavor flav = new DataFlavor(mime); + + List<DataFlavor> flavs = nativeToFlavorMap.get(nat); + if (flavs == null) + { + flavs = new ArrayList<DataFlavor>(); + nativeToFlavorMap.put(nat, flavs); + } + List<String> nats = flavorToNativeMap.get(flav); + if (nats == null) + { + nats = new ArrayList<String>(); + flavorToNativeMap.put(flav, nats); + } + flavs.add(flav); + nats.add(nat); + } + catch (ClassNotFoundException ex) + { + // Skip. + } + catch (MimeTypeParseException ex) + { + // Skip. + } + } + } + + /** * Maps the specified <code>DataFlavor</code> objects to the native * data type name. The returned <code>Map</code> has keys that are * the data flavors and values that are strings. The returned map @@ -98,9 +190,9 @@ * * @return A <code>Map</code> of native data types to data flavors. */ - public Map getNativesForFlavors (DataFlavor[] flavors) + public Map<DataFlavor, String> getNativesForFlavors (DataFlavor[] flavors) { - return new HashMap(); + return new HashMap<DataFlavor, String>(); } /** @@ -114,9 +206,9 @@ * * @return A <code>Map</code> of data flavors to native type names. */ - public Map getFlavorsForNatives (String[] natives) + public Map<String, DataFlavor> getFlavorsForNatives (String[] natives) { - return new HashMap(); + return new HashMap<String, DataFlavor>(); } /** @@ -263,16 +355,52 @@ * specified native and a DataFlavor whose MIME type is a decoded * version of the native. */ - public List getFlavorsForNative (String nat) - throws NotImplementedException + public List<DataFlavor> getFlavorsForNative(String nat) { - throw new Error ("Not implemented"); + List<DataFlavor> ret = new ArrayList<DataFlavor>(); + if (nat == null) + { + Collection<List<DataFlavor>> all = nativeToFlavorMap.values(); + for (List<DataFlavor> list : all) + { + for (DataFlavor flav : list) + { + if (! ret.contains(flav)) + ret.add(flav); + } + } + } + else + { + List<DataFlavor> list = nativeToFlavorMap.get(nat); + if (list != null) + ret.addAll(list); + } + return ret; } - public List getNativesForFlavor (DataFlavor flav) - throws NotImplementedException + public List<String> getNativesForFlavor (DataFlavor flav) { - throw new Error ("Not implemented"); + List<String> ret = new ArrayList<String>(); + if (flav == null) + { + Collection<List<String>> all = flavorToNativeMap.values(); + for (List<String> list : all) + { + for (String nat : list) + { + if (! ret.contains(nat)) + ret.add(nat); + } + } + } + else + { + List<String> list = flavorToNativeMap.get(flav); + if (list != null) + ret.addAll(list); + } + return ret; } /** @@ -298,10 +426,10 @@ { if ((nativeStr == null) || (flavor == null)) throw new NullPointerException(); - List flavors = (List) nativeToFlavorMap.get(nativeStr); + List<DataFlavor> flavors = nativeToFlavorMap.get(nativeStr); if (flavors == null) { - flavors = new ArrayList(); + flavors = new ArrayList<DataFlavor>(); nativeToFlavorMap.put(nativeStr, flavors); } else @@ -336,10 +464,10 @@ { if ((nativeStr == null) || (flavor == null)) throw new NullPointerException(); - List natives = (List) flavorToNativeMap.get(flavor); + List<String> natives = flavorToNativeMap.get(flavor); if (natives == null) { - natives = new ArrayList(); + natives = new ArrayList<String>(); flavorToNativeMap.put(flavor, natives); } else Modified: trunk/core/src/classpath/java/java/awt/event/ComponentEvent.java =================================================================== --- trunk/core/src/classpath/java/java/awt/event/ComponentEvent.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/event/ComponentEvent.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -1,5 +1,5 @@ /* ComponentEvent.java -- notification of events for components - Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 1999, 2002, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -114,24 +114,27 @@ */ public String paramString() { + StringBuffer s = new StringBuffer(); + // Unlike Sun, we don't throw NullPointerException or ClassCastException // when source was illegally changed. - switch (id) - { - case COMPONENT_MOVED: - return "COMPONENT_MOVED " - + (source instanceof Component - ? ((Component) source).getBounds() : (Object) ""); - case COMPONENT_RESIZED: - return "COMPONENT_RESIZED " - + (source instanceof Component - ? ((Component) source).getBounds() : (Object) ""); - case COMPONENT_SHOWN: - return "COMPONENT_SHOWN"; - case COMPONENT_HIDDEN: - return "COMPONENT_HIDDEN"; - default: + if (id == COMPONENT_MOVED) + s.append("COMPONENT_MOVED "); + else if (id == COMPONENT_RESIZED) + s.append("COMPONENT_RESIZED "); + else if (id == COMPONENT_SHOWN) + s.append("COMPONENT_SHOWN "); + else if (id == COMPONENT_HIDDEN) + s.append("COMPONENT_HIDDEN "); + else return "unknown type"; + + s.append("(").append(getComponent().getX()).append(",") + .append(getComponent().getY()).append(" ") + .append(getComponent().getWidth()).append("x") + .append(getComponent().getHeight()).append(")"); + + return s.toString(); } - } + } // class ComponentEvent Modified: trunk/core/src/classpath/java/java/awt/font/LineBreakMeasurer.java =================================================================== --- trunk/core/src/classpath/java/java/awt/font/LineBreakMeasurer.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/font/LineBreakMeasurer.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -1,5 +1,5 @@ /* LineBreakMeasurer.java - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,84 +38,114 @@ package java.awt.font; -import gnu.classpath.NotImplementedException; - import java.text.AttributedCharacterIterator; +import java.text.AttributedString; import java.text.BreakIterator; +import java.awt.Shape; public final class LineBreakMeasurer { - private AttributedCharacterIterator ci; - private FontRenderContext frc; - private BreakIterator bi; + private AttributedCharacterIterator text; + private int position; + private TextMeasurer tm; + private int numChars; - /** - * Constructs a <code>LineBreakMeasurer</code> object. - */ - public LineBreakMeasurer (AttributedCharacterIterator text, - FontRenderContext frc) - { - this (text, null, frc); - } - - /** - * Constructs a <code>LineBreakMeasurer</code> object. - */ - public LineBreakMeasurer (AttributedCharacterIterator text, + public LineBreakMeasurer(AttributedCharacterIterator text, BreakIterator breakIter, FontRenderContext frc) { - this.ci = text; - this.bi = breakIter; - this.frc = frc; + this( text, frc ); } - public void deleteChar (AttributedCharacterIterator newParagraph, - int deletePos) - throws NotImplementedException + public LineBreakMeasurer(AttributedCharacterIterator text, + FontRenderContext frc) { - throw new Error ("not implemented"); + this.text = text; + position = 0; + numChars = text.getEndIndex(); + tm = new TextMeasurer( text, frc ); } - public int getPosition () + public void deleteChar(AttributedCharacterIterator newParagraph, + int deletePos) { - return ci.getIndex (); + tm.deleteChar( newParagraph, deletePos ); + position = 0; } - public void insertChar (AttributedCharacterIterator newParagraph, + public void insertChar(AttributedCharacterIterator newParagraph, int insertPos) - throws NotImplementedException { - throw new Error ("not implemented"); + tm.insertChar( newParagraph, insertPos ); + position = 0; } - public TextLayout nextLayout (float wrappingWidth) - throws NotImplementedException + public TextLayout nextLayout(float wrappingWidth) { - throw new Error ("not implemented"); + return nextLayout( wrappingWidth, numChars, false ); } - public TextLayout nextLayout (float wrappingWidth, int offsetLimit, + public TextLayout nextLayout(float wrappingWidth, int offsetLimit, boolean requireNextWord) - throws NotImplementedException { - throw new Error ("not implemented"); + int next = nextOffset( wrappingWidth, offsetLimit, requireNextWord ); + TextLayout tl = tm.getLayout( position, next ); + position = next; + return tl; } - public int nextOffset (float wrappingWidth) - throws NotImplementedException + public int nextOffset(float wrappingWidth) { - throw new Error ("not implemented"); + return nextOffset( wrappingWidth, numChars, false ); } - public int nextOffset (float wrappingWidth, int offsetLimit, + public int nextOffset(float wrappingWidth, int offsetLimit, boolean requireNextWord) - throws NotImplementedException { - throw new Error ("not implemented"); + int guessOffset = tm.getLineBreakIndex(position, wrappingWidth); + if( offsetLimit > numChars ) + offsetLimit = numChars; + + if( guessOffset > offsetLimit ) + { + text.setIndex( offsetLimit ); + return offsetLimit; + } + + text.setIndex( guessOffset ); + + // If we're on a breaking character, return directly + if( Character.isWhitespace( text.current() ) ) + return guessOffset; + + // Otherwise jump forward or backward to the last such char. + if( !requireNextWord ) + while( !Character.isWhitespace( text.previous() ) && + guessOffset > position ) + guessOffset--; + else + while( !Character.isWhitespace( text.next() ) && + guessOffset < offsetLimit ) + guessOffset++; + + if( guessOffset > offsetLimit ) + { + text.setIndex( offsetLimit ); + return offsetLimit; } - public void setPosition (int newPosition) + text.setIndex( guessOffset ); + + return guessOffset; + } + + public void setPosition(int newPosition) { - ci.setIndex (newPosition); + position = newPosition; } + + public int getPosition() + { + return position; + } } + Modified: trunk/core/src/classpath/java/java/awt/font/TextHitInfo.java =================================================================== --- trunk/core/src/classpath/java/java/awt/font/TextHitInfo.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/font/TextHitInfo.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -81,6 +81,9 @@ public boolean equals(TextHitInfo hitInfo) { + if (hitInfo == null) + return false; + return (charIndex == hitInfo.getCharIndex ()) && (leadingEdge == hitInfo.isLeadingEdge ()); } @@ -97,7 +100,7 @@ public static TextHitInfo beforeOffset(int offset) { - return new TextHitInfo (offset, false); + return new TextHitInfo ((offset - 1), false); } public static TextHitInfo afterOffset(int offset) Modified: trunk/core/src/classpath/java/java/awt/font/TextLayout.java =================================================================== --- trunk/core/src/classpath/java/java/awt/font/TextLayout.java 2007-01-07 18:39:36 UTC (rev 3042) +++ trunk/core/src/classpath/java/java/awt/font/TextLayout.java 2007-01-07 18:41:27 UTC (rev 3043) @@ -38,19 +38,18 @@ package java.awt.font; -import gnu.classpath.NotImplementedException; - import java.awt.Font; import java.awt.Graphics2D; import java.awt.Shape; -import java.awt.Toolkit; import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; +import java.text.CharacterIterator; import java.text.AttributedCharacterIterator; -import java.text.AttributedString; import java.text.Bidi; +import java.util.ArrayList; import java.util.Map; /** @@ -58,21 +57,94 @@ */ public final class TextLayout implements Cloneable { - private GlyphVector[] runs; - private Font font; + /** + * Holds the layout data that belongs to one run of characters. + */ + private class Run + { + /** + * The actual glyph vector. + */ + GlyphVector glyphVector; + + /** + * The font for this text run. + */ + Font font; + + /** + * The start of the run. + */ + int runStart; + + /** + * The end of the run. + */ + int runEnd; + + /** + * The layout location of the beginning of the run. + */ + float location; + + /** + * Initializes the Run instance. + * + * @param gv the glyph vector + * @param start the start index of the run + * @param end the end index of the run + */ + Run(GlyphVector gv, Font f, int start, int end) + { + glyphVector = gv; + font = f; + runStart = start; + runEnd = end; + } + + /** + * Returns <code>true</code> when this run is left to right, + * <code>false</code> otherwise. + * + * @return <code>true</code> when this run is left to right, + * <code>false</code> otherwise + */ + boolean isLeftToRight() + { + return (glyphVector.getLayoutFlags() & GlyphVector.FLAG_RUN_RTL) == 0; + } + } + + /** + * The laid out character runs. + */ + private Run[] runs; + private FontRenderContext frc; - private String string; + private char[] string; + private int offset; + private int length; private Rectangle2D boundsCache; private LineMetrics lm; /** - * Start and end character indices of the runs. - * First index is the run number, second is 0 or 1 for the starting - * and ending character index of the run, respectively. + * The total advance of this text layout. This is cache for maximum + * performance. */ - private int[][] runIndices; + private float totalAdvance = -1F; + + /** + * The cached natural bounds. + */ + private Rectangle2D naturalBounds; /** + * Character indices. + * Fixt index is the glyphvector, second index is the (first) glyph. + */ + private int[][] charIndices; + + /** * Base directionality, determined from the first char. */ private boolean leftToRight; @@ -83,87 +155,249 @@ private boolean hasWhitespace = false; /** + * The {@link Bidi} object that is used for reordering and by + * {@link #getCharacterLevel(int)}. + */ + private Bidi bidi; + + /** + * Mpas the logical position of each individual character in the original + * string to its visual position. + */ + private int[] logicalToVisual; + + /** + * Maps visual positions of a character to its logical position + * in the original string. + */ + private int[] visualToLogical; + + /** + * The cached hashCode. + */ + private int hash; + + /** * The default caret policy. */ - static TextLayout.CaretPolicy DEFAULT_CARET_POLICY = new CaretPolicy(); + public static final TextLayout.CaretPolicy DEFAULT_CARET_POLICY = + new CaretPolicy(); /** * Constructs a TextLayout. */ - public TextLayout (String string, Font font, FontRenderContext frc) + public TextLayout (String str, Font font, FontRenderContext frc) { - this.font = font; this.frc = frc; - this.string = string; - lm = font.getLineMetrics(string, frc); + string = str.toCharArray(); + offset = 0; + length = this.string.length; + lm = font.getLineMetrics(this.string, offset, length, frc); // Get base direction and whitespace info getStringProperties(); - if( Bidi.requiresBidi( string.toCharArray(), 0, string.length() ) ) + if (Bidi.requiresBidi(string, offset, offset + length)) { - Bidi bidi = new Bidi( string, leftToRight ? - Bidi.DIRECTION_LEFT_TO_RIGHT : - Bidi.DIRECTION_RIGHT_TO_LEFT ); + bidi = new Bidi(str, leftToRight ? Bidi.DIRECTION_LEFT_TO_RIGHT + : Bidi.DIRECTION_RIGHT_TO_LEFT ); int rc = bidi.getRunCount(); byte[] table = new byte[ rc ]; for(int i = 0; i < table.length; i++) table[i] = (byte)bidi.getRunLevel(i); - runs = new GlyphVector[ rc ]; - runIndices = new int[rc][2]; - for(int i = 0; i < runs.length; i++) + runs = new Run[rc]; + for(int i = 0; i < rc; i... [truncated message content] |
From: <ls...@us...> - 2007-01-07 18:39:40
|
Revision: 3042 http://jnode.svn.sourceforge.net/jnode/?rev=3042&view=rev Author: lsantha Date: 2007-01-07 10:39:36 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/gnu/gnu/java/io/Base64InputStream.java trunk/core/src/classpath/gnu/gnu/java/lang/InstrumentationImpl.java trunk/core/src/classpath/gnu/gnu/java/lang/management/BeanImpl.java trunk/core/src/classpath/gnu/gnu/java/lang/management/MemoryMXBeanImpl.java trunk/core/src/classpath/gnu/gnu/java/lang/management/MemoryPoolMXBeanImpl.java trunk/core/src/classpath/gnu/gnu/java/lang/management/OperatingSystemMXBeanImpl.java trunk/core/src/classpath/gnu/gnu/java/lang/management/ThreadMXBeanImpl.java trunk/core/src/classpath/gnu/gnu/java/lang/reflect/ClassSignatureParser.java trunk/core/src/classpath/gnu/gnu/java/lang/reflect/GenericSignatureParser.java trunk/core/src/classpath/gnu/gnu/java/lang/reflect/MethodSignatureParser.java trunk/core/src/classpath/gnu/gnu/java/nio/charset/ByteCharset.java trunk/core/src/classpath/gnu/gnu/java/nio/charset/ISO_8859_1.java trunk/core/src/classpath/gnu/gnu/java/nio/charset/US_ASCII.java trunk/core/src/classpath/gnu/gnu/java/rmi/server/ActivatableRef.java trunk/core/src/classpath/gnu/gnu/java/rmi/server/RMIObjectInputStream.java trunk/core/src/classpath/gnu/gnu/java/security/Engine.java trunk/core/src/classpath/gnu/gnu/java/security/x509/X509Certificate.java trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/CertificatePolicies.java trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/ExtendedKeyUsage.java trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/Extension.java trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/GeneralNames.java trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/IssuerAlternativeNames.java trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/SubjectAlternativeNames.java trunk/core/src/classpath/gnu/gnu/java/util/regex/RESyntax.java trunk/core/src/classpath/gnu/gnu/java/util/regex/RETokenNamedProperty.java trunk/core/src/classpath/gnu/gnu/java/util/regex/RETokenRepeated.java trunk/core/src/classpath/gnu/gnu/javax/crypto/RSACipherImpl.java trunk/core/src/classpath/gnu/gnu/javax/crypto/jce/cipher/CipherAdapter.java trunk/core/src/classpath/gnu/gnu/javax/crypto/pad/PKCS7.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/InputSecurityParameters.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SimpleSessionContext.java Modified: trunk/core/src/classpath/gnu/gnu/java/io/Base64InputStream.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/io/Base64InputStream.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/io/Base64InputStream.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -139,7 +139,9 @@ while (count < len) { int i; - while (Character.isWhitespace((char) (i = in.read()))); + while (Character.isWhitespace((char) (i = in.read()))) + ; + int pos = BASE_64.indexOf((char) i); if (pos >= 0) { @@ -173,11 +175,13 @@ case 1: throw new IOException("malformed Base-64 input"); case 2: - while (Character.isWhitespace((char) (i = in.read()))); + while (Character.isWhitespace((char) (i = in.read()))) + ; if (i != BASE_64_PAD) throw new IOException("malformed Base-64 input"); case 3: - while (Character.isWhitespace((char) (i = in.read()))); + while (Character.isWhitespace((char) (i = in.read()))) + ; } eof = true; break; Modified: trunk/core/src/classpath/gnu/gnu/java/lang/InstrumentationImpl.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/lang/InstrumentationImpl.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/lang/InstrumentationImpl.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -1,6 +1,6 @@ /* InstrumentationImpl.java -- GNU implementation of java.lang.instrument.Instrumentation - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -63,11 +63,11 @@ { /* List of transformers */ - /* FIXME[GENERICS]: Should be ClassFileTransformer list */ - private ArrayList transformers = new ArrayList(); + private ArrayList<ClassFileTransformer> transformers = + new ArrayList<ClassFileTransformer>(); - private InstrumentationImpl() + InstrumentationImpl() { } @@ -210,9 +210,8 @@ * * @return the new class file */ - /* FIXME[GENERICS]: Should be Class<?> */ public byte[] callTransformers(ClassLoader loader, String className, - Class classBeingRedefined, ProtectionDomain protectionDomain, + Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { byte[] newBuffer = null; @@ -220,11 +219,10 @@ ClassFileTransformer current; synchronized (transformers) { - Iterator i = transformers.iterator(); + Iterator<ClassFileTransformer> i = transformers.iterator(); while (i.hasNext()) { - /* FIXME[GENERICS]: Remove cast */ - current = (ClassFileTransformer) i.next(); + current = i.next(); try { newBuffer = current.transform(loader, className, Modified: trunk/core/src/classpath/gnu/gnu/java/lang/management/BeanImpl.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/lang/management/BeanImpl.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/lang/management/BeanImpl.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -201,32 +201,36 @@ return ((Enum) value).name(); Class vClass = value.getClass(); if (vClass.isArray()) - return value; + vClass = vClass.getComponentType(); String cName = vClass.getName(); String[] allowedTypes = OpenType.ALLOWED_CLASSNAMES; for (int a = 0; a < allowedTypes.length; ++a) if (cName.equals(allowedTypes[a])) return value; + OpenMBeanInfo info = (OpenMBeanInfo) getMBeanInfo(); + MBeanAttributeInfo[] attribs = + (MBeanAttributeInfo[]) info.getAttributes(); + OpenType type = null; + for (int a = 0; a < attribs.length; ++a) + if (attribs[a].getName().equals(attribute)) + type = ((OpenMBeanAttributeInfo) attribs[a]).getOpenType(); if (value instanceof List) { + try + { + Class e = + Class.forName(((ArrayType) type).getElementOpenType().getClassName()); List l = (List) value; - Class e = null; - TypeVariable[] vars = vClass.getTypeParameters(); - for (int a = 0; a < vars.length; ++a) - if (vars[a].getName().equals("E")) - e = (Class) vars[a].getGenericDeclaration(); - if (e == null) - e = Object.class; Object[] array = (Object[]) Array.newInstance(e, l.size()); return l.toArray(array); } - OpenMBeanInfo info = (OpenMBeanInfo) getMBeanInfo(); - OpenMBeanAttributeInfo[] attribs = - (OpenMBeanAttributeInfo[]) info.getAttributes(); - OpenType type = null; - for (int a = 0; a < attribs.length; ++a) - if (attribs[a].getName().equals("attribute")) - type = attribs[a].getOpenType(); + catch (ClassNotFoundException e) + { + throw (InternalError) (new InternalError("The class of the list " + + "element type could not " + + "be created").initCause(e)); + } + } if (value instanceof Map) { TabularType ttype = (TabularType) type; @@ -425,6 +429,34 @@ return new OpenMBeanParameterInfoSupport("TransParam", "Translated parameter", SimpleType.VOID); + if (type.startsWith("java.util.Map")) + { + int lparam = type.indexOf("<"); + int comma = type.indexOf(",", lparam); + int rparam = type.indexOf(">", comma); + String key = type.substring(lparam + 1, comma).trim(); + OpenType k = translate(key).getOpenType(); + OpenType v = translate(type.substring(comma + 1, rparam).trim()).getOpenType(); + CompositeType ctype = new CompositeType(Map.class.getName(), Map.class.getName(), + new String[] { "key", "value" }, + new String[] { "Map key", "Map value"}, + new OpenType[] { k, v}); + TabularType ttype = new TabularType(key, key, ctype, + new String[] { "key" }); + return new OpenMBeanParameterInfoSupport("TransParam", + "Translated parameter", + ttype); + } + if (type.startsWith("java.util.List")) + { + int lparam = type.indexOf("<"); + int rparam = type.indexOf(">"); + OpenType e = translate(type.substring(lparam + 1, rparam).trim()).getOpenType(); + return new OpenMBeanParameterInfoSupport("TransParam", + "Translated parameter", + new ArrayType(1, e) + ); + } Class c; try { @@ -432,8 +464,9 @@ } catch (ClassNotFoundException e) { - throw new InternalError("The class for a type used in a management bean " + - "could not be loaded."); + throw (InternalError) + (new InternalError("The class for a type used in a management bean " + + "could not be loaded.").initCause(e)); } if (c.isEnum()) { @@ -450,9 +483,9 @@ try { c.getMethod("from", new Class[] { CompositeData.class }); - Method[] methods = c.getMethods(); - List names = new ArrayList(); - List types = new ArrayList(); + Method[] methods = c.getDeclaredMethods(); + List<String> names = new ArrayList<String>(); + List<OpenType> types = new ArrayList<OpenType>(); for (int a = 0; a < methods.length; ++a) { String name = methods[a].getName(); @@ -462,10 +495,10 @@ types.add(getTypeFromClass(methods[a].getReturnType())); } } - String[] fields = (String[]) names.toArray(); + String[] fields = names.toArray(new String[names.size()]); CompositeType ctype = new CompositeType(c.getName(), c.getName(), fields, fields, - (OpenType[]) types.toArray()); + types.toArray(new OpenType[types.size()])); return new OpenMBeanParameterInfoSupport("TransParam", "Translated parameter", ctype); @@ -474,46 +507,11 @@ { /* Ignored; we expect this if this isn't a from(CompositeData) class */ } - if (Map.class.isAssignableFrom(c)) - { - OpenType k = SimpleType.VOID; - OpenType v = SimpleType.VOID; - TypeVariable[] vars = c.getTypeParameters(); - for (int a = 0; a < vars.length; ++a) - { - if (vars[a].getName().equals("K")) - k = getTypeFromClass((Class) vars[a].getGenericDeclaration()); - if (vars[a].getName().equals("V")) - v = getTypeFromClass((Class) vars[a].getGenericDeclaration()); - } - CompositeType ctype = new CompositeType(Map.class.getName(), Map.class.getName(), - new String[] { "key", "value" }, - new String[] { "Map key", "Map value"}, - new OpenType[] { k, v}); - TabularType ttype = new TabularType(c.getName(), c.getName(), ctype, - new String[] { "key" }); - return new OpenMBeanParameterInfoSupport("TransParam", - "Translated parameter", - ttype); - } - if (List.class.isAssignableFrom(c)) - { - OpenType e = SimpleType.VOID; - TypeVariable[] vars = c.getTypeParameters(); - for (int a = 0; a < vars.length; ++a) - { - if (vars[a].getName().equals("E")) - e = getTypeFromClass((Class) vars[a].getGenericDeclaration()); - } - return new OpenMBeanParameterInfoSupport("TransParam", - "Translated parameter", - new ArrayType(1, e) - ); - } if (c.isArray()) { int depth; - for (depth = 0; c.getName().charAt(depth) == '['; ++depth); + for (depth = 0; c.getName().charAt(depth) == '['; ++depth) + ; OpenType ot = getTypeFromClass(c.getComponentType()); return new OpenMBeanParameterInfoSupport("TransParam", "Translated parameter", Modified: trunk/core/src/classpath/gnu/gnu/java/lang/management/MemoryMXBeanImpl.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/lang/management/MemoryMXBeanImpl.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/lang/management/MemoryMXBeanImpl.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -37,6 +37,8 @@ package gnu.java.lang.management; +import gnu.classpath.ListenerData; + import java.lang.management.MemoryMXBean; import java.lang.management.MemoryNotificationInfo; import java.lang.management.MemoryUsage; @@ -168,49 +170,6 @@ VMMemoryMXBeanImpl.setVerbose(verbose); } - private class ListenerData - { - private NotificationListener listener; - private NotificationFilter filter; - private Object passback; - - public ListenerData(NotificationListener listener, - NotificationFilter filter, Object passback) - { - this.listener = listener; - this.filter = filter; - this.passback = passback; - } - - public NotificationListener getListener() - { - return listener; - } - - public NotificationFilter getFilter() - { - return filter; - } - - public Object getPassback() - { - return passback; - } - - public boolean equals(Object obj) - { - if (obj instanceof ListenerData) - { - ListenerData data = (ListenerData) obj; - return (data.getListener() == listener && - data.getFilter() == filter && - data.getPassback() == passback); - } - return false; - } - - } - public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object passback) Modified: trunk/core/src/classpath/gnu/gnu/java/lang/management/MemoryPoolMXBeanImpl.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/lang/management/MemoryPoolMXBeanImpl.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/lang/management/MemoryPoolMXBeanImpl.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -40,8 +40,8 @@ import gnu.classpath.SystemProperties; import java.lang.management.MemoryPoolMXBean; +import java.lang.management.MemoryType; import java.lang.management.MemoryUsage; -import java.lang.management.MemoryType; import javax.management.NotCompliantMBeanException; @@ -136,7 +136,8 @@ public MemoryType getType() { - return null; + return + MemoryType.valueOf(VMMemoryPoolMXBeanImpl.getType(name)); } public MemoryUsage getUsage() Modified: trunk/core/src/classpath/gnu/gnu/java/lang/management/OperatingSystemMXBeanImpl.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/lang/management/OperatingSystemMXBeanImpl.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/lang/management/OperatingSystemMXBeanImpl.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -82,14 +82,14 @@ return System.getProperty("os.name"); } + public double getSystemLoadAverage() + { + return VMOperatingSystemMXBeanImpl.getSystemLoadAverage(); + } + public String getVersion() { return System.getProperty("os.version"); } - - public double getSystemLoadAverage() { - //todo implement - throw new UnsupportedOperationException(); - } } Modified: trunk/core/src/classpath/gnu/gnu/java/lang/management/ThreadMXBeanImpl.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/lang/management/ThreadMXBeanImpl.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/lang/management/ThreadMXBeanImpl.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -85,6 +85,18 @@ "gnu.java.lang.management.ThreadTimeInitallyEnabled"; /** + * Constant for monitor usage monitoring support. + */ + private static final String MONITOR_SUPPORT = + "gnu.java.lang.management.MonitorUsageMonitoringSupport"; + + /** + * Constant for ownable synchronizer usage monitoring support. + */ + private static final String SYNCHRONIZER_SUPPORT = + "gnu.java.lang.management.OwnableSynchronizerUsageMonitoringSupport"; + + /** * Flag to indicate whether time monitoring is enabled or not. */ private boolean timeEnabled; @@ -112,6 +124,23 @@ contentionEnabled = false; } + public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, + boolean lockedSynchronizers) + { + return getThreadInfo(getAllThreadIds(), lockedMonitors, + lockedSynchronizers); + } + + public long[] findDeadlockedThreads() + { + checkMonitorPermissions(); + if (!isSynchronizerUsageSupported()) + throw new UnsupportedOperationException("Ownable synchronizer usage " + + "monitoring is not provided " + + "by this VM."); + return VMThreadMXBeanImpl.findDeadlockedThreads(); + } + public long[] findMonitorDeadlockedThreads() { checkMonitorPermissions(); @@ -207,6 +236,27 @@ return infos; } + public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, + boolean lockedSynchronizers) + { + checkMonitorPermissions(); + if (lockedMonitors && !isObjectMonitorUsageSupported()) + throw new UnsupportedOperationException("Monitor usage monitoring is " + + "not provided by this VM."); + if (lockedSynchronizers && !isSynchronizerUsageSupported()) + throw new UnsupportedOperationException("Ownable synchronizer usage " + + "monitoring is not provided " + + "by this VM."); + ThreadInfo[] infos = getThreadInfo(ids, Integer.MAX_VALUE); + if (lockedMonitors) + for (ThreadInfo info : infos) + VMThreadMXBeanImpl.getMonitorInfo(info); + if (lockedSynchronizers) + for (ThreadInfo info : infos) + VMThreadMXBeanImpl.getLockInfo(info); + return infos; + } + public long getThreadUserTime(long id) { if (!isThreadCpuTimeSupported()) @@ -231,6 +281,16 @@ return SystemProperties.getProperty(CURRENT_THREAD_TIME_SUPPORT) != null; } + public boolean isObjectMonitorUsageSupported() + { + return SystemProperties.getProperty(MONITOR_SUPPORT) != null; + } + + public boolean isSynchronizerUsageSupported() + { + return SystemProperties.getProperty(SYNCHRONIZER_SUPPORT) != null; + } + public boolean isThreadContentionMonitoringEnabled() { if (isThreadContentionMonitoringSupported()) @@ -287,30 +347,5 @@ "supported."); } - - public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) { - //todo implement - throw new UnsupportedOperationException(); - } - - public long[] findDeadlockedThreads() { - //todo implement - throw new UnsupportedOperationException(); - } - - public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) { - //todo implement - throw new UnsupportedOperationException(); - } - - public boolean isObjectMonitorUsageSupported() { - //todo implement - throw new UnsupportedOperationException(); - } - - public boolean isSynchronizerUsageSupported() { - //todo implement - throw new UnsupportedOperationException(); - } } Modified: trunk/core/src/classpath/gnu/gnu/java/lang/reflect/ClassSignatureParser.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/lang/reflect/ClassSignatureParser.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/lang/reflect/ClassSignatureParser.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -61,7 +61,7 @@ } // SuperclassSignature superclassType = readClassTypeSignature(); - ArrayList interfaces = new ArrayList(); + ArrayList<Type> interfaces = new ArrayList<Type>(); while (peekChar() == 'L') { // SuperinterfaceSignature Modified: trunk/core/src/classpath/gnu/gnu/java/lang/reflect/GenericSignatureParser.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/lang/reflect/GenericSignatureParser.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/lang/reflect/GenericSignatureParser.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -60,11 +60,10 @@ return this; } - /* FIXME[GENERICS]: Remove cast */ public Type[] getBounds() { resolve(bounds); - return (Type[]) bounds.clone(); + return bounds.clone(); } public GenericDeclaration getGenericDeclaration() @@ -141,10 +140,9 @@ return this; } - /* FIXME[GENERICS]: Remove cast */ public Type[] getActualTypeArguments() { - return (Type[]) typeArgs.clone(); + return typeArgs.clone(); } public Type getRawType() @@ -276,12 +274,11 @@ GenericDeclaration d = decl; while (d != null) { - TypeVariable[] vars = d.getTypeParameters(); - for (int a = 0; a < vars.length ; ++a) + for (TypeVariable t : d.getTypeParameters()) { - if (vars[a].getName().equals(name)) + if (t.getName().equals(name)) { - return vars[a]; + return t; } } d = getParent(d); @@ -414,7 +411,7 @@ TypeVariable[] readFormalTypeParameters() { consume('<'); - ArrayList params = new ArrayList(); + ArrayList<TypeVariable> params = new ArrayList<TypeVariable>(); do { // TODO should we handle name clashes? @@ -430,7 +427,7 @@ { String identifier = readIdentifier(); consume(':'); - ArrayList bounds = new ArrayList(); + ArrayList<Type> bounds = new ArrayList<Type>(); if (peekChar() != ':') { bounds.add(readFieldTypeSignature()); @@ -501,7 +498,7 @@ private Type[] readTypeArguments() { consume('<'); - ArrayList list = new ArrayList(); + ArrayList<Type> list = new ArrayList<Type>(); do { list.add(readTypeArgument()); Modified: trunk/core/src/classpath/gnu/gnu/java/lang/reflect/MethodSignatureParser.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/lang/reflect/MethodSignatureParser.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/lang/reflect/MethodSignatureParser.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -72,7 +72,7 @@ typeParameters = new TypeVariable[0]; } consume('('); - ArrayList args = new ArrayList(); + ArrayList<Type> args = new ArrayList<Type>(); while (peekChar() != ')') { args.add(readTypeSignature()); @@ -81,7 +81,7 @@ args.toArray(argTypes); consume(')'); retType = readTypeSignature(); - ArrayList throwsSigs = new ArrayList(); + ArrayList<Type> throwsSigs = new ArrayList<Type>(); while (peekChar() == '^') { consume('^'); Modified: trunk/core/src/classpath/gnu/gnu/java/nio/charset/ByteCharset.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/nio/charset/ByteCharset.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/nio/charset/ByteCharset.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -115,8 +115,8 @@ return CoderResult.OVERFLOW; } - if((c = lookup[(int) (b & 0xFF)]) == NONE); - // return CoderResult.unmappableForLength (1); + if((c = lookup[(int) (b & 0xFF)]) == NONE) + return CoderResult.unmappableForLength (1); out.put (c); } @@ -156,6 +156,22 @@ } } + public boolean canEncode(char c) + { + byte b = (c < lookup.length) ? lookup[c] : 0; + return b != 0 || c == 0; + } + + public boolean canEncode(CharSequence cs) + { + for (int i = 0; i < cs.length(); ++i) + { + if (! canEncode(cs.charAt(i))) + return false; + } + return true; + } + protected CoderResult encodeLoop (CharBuffer in, ByteBuffer out) { // TODO: Optimize this in the case in.hasArray() / out.hasArray() Modified: trunk/core/src/classpath/gnu/gnu/java/nio/charset/ISO_8859_1.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/nio/charset/ISO_8859_1.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/nio/charset/ISO_8859_1.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -128,6 +128,19 @@ super (cs, 1.0f, 1.0f); } + public boolean canEncode(char c) + { + return c <= 0xff; + } + + public boolean canEncode(CharSequence cs) + { + for (int i = 0; i < cs.length(); ++i) + if (! canEncode(cs.charAt(i))) + return false; + return true; + } + protected CoderResult encodeLoop (CharBuffer in, ByteBuffer out) { // TODO: Optimize this in the case in.hasArray() / out.hasArray() Modified: trunk/core/src/classpath/gnu/gnu/java/nio/charset/US_ASCII.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/nio/charset/US_ASCII.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/nio/charset/US_ASCII.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -134,6 +134,19 @@ super (cs, 1.0f, 1.0f); } + public boolean canEncode(char c) + { + return c <= 0x7f; + } + + public boolean canEncode(CharSequence cs) + { + for (int i = 0; i < cs.length(); ++i) + if (! canEncode(cs.charAt(i))) + return false; + return true; + } + protected CoderResult encodeLoop (CharBuffer in, ByteBuffer out) { // TODO: Optimize this in the case in.hasArray() / out.hasArray() @@ -141,7 +154,7 @@ { char c = in.get (); - if (c > Byte.MAX_VALUE) + if (c > 0x7f) { in.position (in.position () - 1); return CoderResult.unmappableForLength (1); Modified: trunk/core/src/classpath/gnu/gnu/java/rmi/server/ActivatableRef.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/rmi/server/ActivatableRef.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/rmi/server/ActivatableRef.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -112,8 +112,10 @@ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + actId = (ActivationID) in.readObject(); + String type = in.readUTF(); + // XXX handle type.equals("") (null reference) super.readExternal(in); - actId = (ActivationID) in.readObject(); } /** @@ -121,8 +123,10 @@ */ public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(actId); + // XXX write a "" if the "nested" reference is a null reference + out.writeUTF("UnicastRef2"); super.writeExternal(out); - out.writeObject(actId); } /** Modified: trunk/core/src/classpath/gnu/gnu/java/rmi/server/RMIObjectInputStream.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/rmi/server/RMIObjectInputStream.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/rmi/server/RMIObjectInputStream.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -1,5 +1,5 @@ /* RMIObjectInputStream.java -- - Copyright (c) 1996, 1997, 1998, 1999, 2002, 2004 + Copyright (c) 1996, 1997, 1998, 1999, 2002, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,11 +39,11 @@ package gnu.java.rmi.server; +import gnu.classpath.VMStackWalker; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; -import java.lang.reflect.Proxy; import java.net.MalformedURLException; import java.rmi.server.RMIClassLoader; import java.util.ArrayList; @@ -57,16 +57,14 @@ } protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { - String annotation = (String)getAnnotation(); - try { - if(annotation == null) - return (RMIClassLoader.loadClass(desc.getName())); - else - return (RMIClassLoader.loadClass(annotation, desc.getName())); + return RMIClassLoader.loadClass( + (String)getAnnotation(), + desc.getName(), + VMStackWalker.firstNonNullClassLoader()); } - catch (MalformedURLException _) { - throw new ClassNotFoundException(desc.getName()); + catch (MalformedURLException x) { + throw new ClassNotFoundException(desc.getName(), x); } } @@ -81,45 +79,16 @@ protected Class resolveProxyClass(String intfs[]) throws IOException, ClassNotFoundException { - String annotation = (String) getAnnotation(); - - Class clss[] = new Class[intfs.length]; - - for (int i = 0; i < intfs.length; i++) - { - if (annotation == null) - clss[i] = RMIClassLoader.loadClass(intfs[i]); - else - clss[i] = RMIClassLoader.loadClass(annotation, intfs[i]); - } - - ClassLoader loader; - - if (clss.length > 0) - { - // Chain all class loaders (they may differ). - ArrayList loaders = new ArrayList(intfs.length); - ClassLoader cx; - for (int i = 0; i < clss.length; i++) - { - cx = clss[i].getClassLoader(); - if (!loaders.contains(cx)) - { - loaders.add(0, cx); - } - } - loader = new CombinedClassLoader(loaders); - } - else - loader = ClassLoader.getSystemClassLoader(); - try { - return Proxy.getProxyClass(loader, clss); + return RMIClassLoader.loadProxyClass( + (String)getAnnotation(), + intfs, + VMStackWalker.firstNonNullClassLoader()); } - catch (IllegalArgumentException e) + catch (MalformedURLException x) { - throw new ClassNotFoundException(null, e); + throw new ClassNotFoundException(null, x); } } Modified: trunk/core/src/classpath/gnu/gnu/java/security/Engine.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/security/Engine.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/security/Engine.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -42,6 +42,7 @@ import java.security.NoSuchAlgorithmException; import java.security.Provider; +import java.util.Enumeration; /** * Generic implementation of the getInstance methods in the various @@ -78,25 +79,22 @@ /** This class cannot be instantiated. */ private Engine() { } - // Class method. - // ------------------------------------------------------------------------ - /** - * Get the implementation for <i>algorithm</i> for service - * <i>service</i> from <i>provider</i>. The service is e.g. - * "Signature", and the algorithm "DSA". + * Return the implementation for <i>algorithm</i> for service <i>service</i> + * from <i>provider</i>. The service is e.g. "Signature", and the algorithm + * "DSA". * * @param service The service name. * @param algorithm The name of the algorithm to get. * @param provider The provider to get the implementation from. - * @return The engine class for the specified algorithm; the object - * returned is typically a subclass of the SPI class for that - * service, but callers should check that this is so. - * @throws NoSuchAlgorithmException If the implementation cannot be - * found or cannot be instantiated. - * @throws InvocationTargetException If the SPI class's constructor - * throws an exception. - * @throws IllegalArgumentException If any of the three arguments are null. + * @return The engine class for the specified algorithm; the object returned + * is typically a subclass of the SPI class for that service, but + * callers should check that this is so. + * @throws NoSuchAlgorithmException If the implementation cannot be found or + * cannot be instantiated. + * @throws InvocationTargetException If the SPI class's constructor throws an + * exception. + * @throws IllegalArgumentException If any of the three arguments is null. */ public static Object getInstance(String service, String algorithm, Provider provider) @@ -106,107 +104,145 @@ } /** - * Get the implementation for <i>algorithm</i> for service - * <i>service</i> from <i>provider</i>, passing <i>initArgs</i> to the - * SPI class's constructor (which cannot be null; pass a zero-length - * array if the SPI takes no arguments). The service is e.g. - * "Signature", and the algorithm "DSA". + * Return the implementation for <i>algorithm</i> for service <i>service</i> + * from <i>provider</i>, passing <i>initArgs</i> to the SPI class's + * constructor (which cannot be null; pass a zero-length array if the SPI + * takes no arguments). The service is e.g. "Signature", and the algorithm + * "DSA". * * @param service The service name. * @param algorithm The name of the algorithm to get. * @param provider The provider to get the implementation from. - * @param initArgs The arguments to pass to the SPI class's - * constructor (cannot be null). - * @return The engine class for the specified algorithm; the object - * returned is typically a subclass of the SPI class for that - * service, but callers should check that this is so. - * @throws NoSuchAlgorithmException If the implementation cannot be - * found or cannot be instantiated. - * @throws InvocationTargetException If the SPI class's constructor - * throws an exception. - * @throws IllegalArgumentException If any of the four arguments are null. + * @param initArgs The arguments to pass to the SPI class's constructor + * (cannot be null). + * @return The engine class for the specified algorithm; the object returned + * is typically a subclass of the SPI class for that service, but + * callers should check that this is so. + * @throws NoSuchAlgorithmException If the implementation cannot be found or + * cannot be instantiated. + * @throws InvocationTargetException If the SPI class's constructor throws an + * exception. + * @throws IllegalArgumentException If any of the four arguments is + * <code>null</code> or if either <code>service</code>, or + * <code>algorithm</code> is an empty string. */ public static Object getInstance(String service, String algorithm, Provider provider, Object[] initArgs) throws InvocationTargetException, NoSuchAlgorithmException { - if (service != null) + if (service == null) + throw new IllegalArgumentException("service MUST NOT be null"); service = service.trim(); - - if (algorithm != null) + if (service.length() == 0) + throw new IllegalArgumentException("service MUST NOT be empty"); + if (algorithm == null) + throw new IllegalArgumentException("algorithm MUST NOT be null"); algorithm = algorithm.trim(); + if (algorithm.length() == 0) + throw new IllegalArgumentException("algorithm MUST NOT be empty"); + if (provider == null) + throw new IllegalArgumentException("provider MUST NOT be null"); + if (initArgs == null) + throw new IllegalArgumentException("Constructor's parameters MUST NOT be null"); - if (service == null || service.length() == 0 - || algorithm == null || algorithm.length() == 0 - || provider == null || initArgs == null) - throw new IllegalArgumentException(); - - // If there is no property "service.algorithm" - if (provider.getProperty(service + "." + algorithm) == null) + Enumeration enumer = provider.propertyNames(); + String key; + String alias; + int count = 0; + boolean algorithmFound = false; + StringBuilder sb = new StringBuilder(); + while (enumer.hasMoreElements()) { - // Iterate through aliases, until we find the class name or resolve - // too many aliases. - String alias = null; - int count = 0; - while ((alias = provider.getProperty( - ALG_ALIAS + service + "." + algorithm)) != null) + key = (String) enumer.nextElement(); + if (key.equalsIgnoreCase(service + "." + algorithm)) { - if (algorithm.equals(alias)) // Refers to itself! + // remove the service portion from the key + algorithm = key.substring(service.length() + 1); + algorithmFound = true; break; + } + else if (key.equalsIgnoreCase(ALG_ALIAS + service + "." + algorithm)) + { + alias = (String) provider.getProperty(key); + if (! algorithm.equalsIgnoreCase(alias)) // does not refer to itself + { algorithm = alias; if (count++ > MAX_ALIASES) - throw new NoSuchAlgorithmException("too many aliases"); + { + sb.append("Algorithm [").append(algorithm) + .append("] of type [").append(service) + .append("] from provider [").append(provider) + .append("] has too many aliases"); + throw new NoSuchAlgorithmException(sb.toString()); } - if (provider.getProperty(service + "." + algorithm) == null) - throw new NoSuchAlgorithmException(algorithm); + // need to reset enumeration to now look for the alias + enumer = provider.propertyNames(); + } + } } - // Find and instantiate the implementation. + if (! algorithmFound) + { + sb.append("Algorithm [").append(algorithm).append("] of type [") + .append(service).append("] from provider [") + .append(provider).append("] is not found"); + throw new NoSuchAlgorithmException(sb.toString()); + } + + // Find and instantiate the implementation Class clazz = null; ClassLoader loader = provider.getClass().getClassLoader(); Constructor constructor = null; - String error = algorithm; - + String className = provider.getProperty(service + "." + algorithm); + sb.append("Class [").append(className).append("] for algorithm [") + .append(algorithm).append("] of type [").append(service) + .append("] from provider [").append(provider).append("] "); + Throwable cause = null; try { if (loader != null) - clazz = loader.loadClass(provider.getProperty(service+"."+algorithm)); + clazz = loader.loadClass(className); else - clazz = Class.forName(provider.getProperty(service+"."+algorithm)); + clazz = Class.forName(className); constructor = getCompatibleConstructor(clazz, initArgs); return constructor.newInstance(initArgs); } - catch (ClassNotFoundException cnfe) + catch (ClassNotFoundException x) { - error = "class not found: " + algorithm; + sb.append("cannot not be found"); + cause = x; } - catch (IllegalAccessException iae) + catch (IllegalAccessException x) { - error = "illegal access: " + iae.getMessage(); + sb.append("cannot be accessed"); + cause = x; } - catch (InstantiationException ie) + catch (InstantiationException x) { - error = "instantiation exception: " + ie.getMessage(); + sb.append("cannot be instantiated"); + cause = x; } - catch (ExceptionInInitializerError eiie) + catch (ExceptionInInitializerError x) { - error = "exception in initializer: " + eiie.getMessage(); + sb.append("cannot be initialized"); + cause = x; } - catch (SecurityException se) + catch (SecurityException x) { - error = "security exception: " + se.getMessage(); + sb.append("caused a security violation"); + cause = x; } - catch (NoSuchMethodException nsme) + catch (NoSuchMethodException x) { - error = "no appropriate constructor found"; + sb.append("does not have/expose an appropriate constructor"); + cause = x; } - throw new NoSuchAlgorithmException(error); + NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString()); + x.initCause(cause); + throw x; } - // Own methods. - // ------------------------------------------------------------------------ - /** * Find a constructor in the given class that can take the specified * argument list, allowing any of which to be null. Modified: trunk/core/src/classpath/gnu/gnu/java/security/x509/X509Certificate.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/security/x509/X509Certificate.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/security/x509/X509Certificate.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -1,5 +1,5 @@ /* X509Certificate.java -- X.509 certificate. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -48,6 +48,7 @@ import gnu.java.security.x509.ext.BasicConstraints; import gnu.java.security.x509.ext.ExtendedKeyUsage; import gnu.java.security.x509.ext.Extension; +import gnu.java.security.x509.ext.GeneralName; import gnu.java.security.x509.ext.IssuerAlternativeNames; import gnu.java.security.x509.ext.KeyUsage; import gnu.java.security.x509.ext.SubjectAlternativeNames; @@ -103,6 +104,7 @@ // Constants and fields. // ------------------------------------------------------------------------ + private static final long serialVersionUID = -2491127588187038216L; private static final Logger logger = SystemLogger.SYSTEM; protected static final OID ID_DSA = new OID ("1.2.840.10040.4.1"); @@ -133,7 +135,7 @@ protected transient PublicKey subjectKey; protected transient BitString issuerUniqueId; protected transient BitString subjectUniqueId; - protected transient Map extensions; + protected transient Map<OID, Extension> extensions; // Signature. protected transient OID sigAlgId; @@ -157,7 +159,7 @@ throws CertificateException, IOException { super(); - extensions = new HashMap(); + extensions = new HashMap<OID, Extension>(); try { parse(encoded); @@ -178,7 +180,7 @@ protected X509Certificate() { - extensions = new HashMap(); + extensions = new HashMap<OID, Extension>(); } // X509Certificate methods. @@ -316,17 +318,15 @@ return null; } - public List getExtendedKeyUsage() throws CertificateParsingException + public List<String> getExtendedKeyUsage() throws CertificateParsingException { Extension e = getExtension(ExtendedKeyUsage.ID); if (e != null) { - List a = ((ExtendedKeyUsage) e.getValue()).getPurposeIds(); - List b = new ArrayList(a.size()); - for (Iterator it = a.iterator(); it.hasNext(); ) - { - b.add(it.next().toString()); - } + List<OID> a = ((ExtendedKeyUsage) e.getValue()).getPurposeIds(); + List<String> b = new ArrayList<String>(a.size()); + for (OID oid : a) + b.add(oid.toString()); return Collections.unmodifiableList(b); } return null; @@ -342,24 +342,44 @@ return -1; } - public Collection getSubjectAlternativeNames() + public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException { Extension e = getExtension(SubjectAlternativeNames.ID); if (e != null) { - return ((SubjectAlternativeNames) e.getValue()).getNames(); + List<GeneralName> names + = ((SubjectAlternativeNames) e.getValue()).getNames(); + List<List<?>> list = new ArrayList<List<?>>(names.size()); + for (GeneralName name : names) + { + List<Object> n = new ArrayList<Object>(2); + n.add(name.kind().tag()); + n.add(name.name()); + list.add(n); + } + return list; } return null; } - public Collection getIssuerAlternativeNames() + public Collection<List<?>> getIssuerAlternativeNames() throws CertificateParsingException { Extension e = getExtension(IssuerAlternativeNames.ID); if (e != null) { - return ((IssuerAlternativeNames) e.getValue()).getNames(); + List<GeneralName> names + = ((IssuerAlternativeNames) e.getValue()).getNames(); + List<List<?>> list = new ArrayList<List<?>>(names.size()); + for (GeneralName name : names) + { + List<Object> n = new ArrayList<Object>(2); + n.add(name.kind().tag()); + n.add(name.name()); + list.add(n); + } + return list; } return null; } @@ -378,24 +398,22 @@ return false; } - public Set getCriticalExtensionOIDs() + public Set<String> getCriticalExtensionOIDs() { - HashSet s = new HashSet(); - for (Iterator it = extensions.values().iterator(); it.hasNext(); ) + HashSet<String> s = new HashSet<String>(); + for (Extension e : extensions.values()) { - Extension e = (Extension) it.next(); if (e.isCritical()) s.add(e.getOid().toString()); } return Collections.unmodifiableSet(s); } - public Set getNonCriticalExtensionOIDs() + public Set<String> getNonCriticalExtensionOIDs() { - HashSet s = new HashSet(); - for (Iterator it = extensions.values().iterator(); it.hasNext(); ) + HashSet<String> s = new HashSet<String>(); + for (Extension e : extensions.values()) { - Extension e = (Extension) it.next(); if (!e.isCritical()) s.add(e.getOid().toString()); } Modified: trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/CertificatePolicies.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/CertificatePolicies.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/CertificatePolicies.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -1,5 +1,5 @@ /* CertificatePolicies.java -- certificate policy extension. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -61,8 +61,8 @@ public static final OID ID = new OID("2.5.29.32"); - private final List policies; - private final Map policyQualifierInfos; + private final List<OID> policies; + private final Map<OID, List<PolicyQualifierInfo>> policyQualifierInfos; // Constructor. // ------------------------------------------------------------------------- @@ -76,8 +76,9 @@ throw new IOException("malformed CertificatePolicies"); int len = 0; - LinkedList policyList = new LinkedList(); - HashMap qualifierMap = new HashMap(); + LinkedList<OID> policyList = new LinkedList<OID>(); + HashMap<OID, List<PolicyQualifierInfo>> qualifierMap + = new HashMap<OID, List<PolicyQualifierInfo>>(); while (len < pol.getLength()) { DERValue policyInfo = der.read(); @@ -92,7 +93,7 @@ { DERValue qual = der.read(); int len2 = 0; - LinkedList quals = new LinkedList(); + LinkedList<PolicyQualifierInfo> quals = new LinkedList<PolicyQualifierInfo>(); while (len2 < qual.getLength()) { val = der.read(); @@ -109,8 +110,8 @@ policyQualifierInfos = Collections.unmodifiableMap(qualifierMap); } - public CertificatePolicies (final List policies, - final Map policyQualifierInfos) + public CertificatePolicies (final List<OID> policies, + final Map<OID, List<PolicyQualifierInfo>> policyQualifierInfos) { for (Iterator it = policies.iterator(); it.hasNext(); ) if (!(it.next() instanceof OID)) @@ -129,54 +130,69 @@ throw new IllegalArgumentException ("policyQualifierInfos values must be Lists of PolicyQualifierInfos"); } - this.policies = Collections.unmodifiableList (new ArrayList (policies)); + this.policies = Collections.unmodifiableList (new ArrayList<OID>(policies)); this.policyQualifierInfos = Collections.unmodifiableMap - (new HashMap (policyQualifierInfos)); + (new HashMap<OID, List<PolicyQualifierInfo>>(policyQualifierInfos)); } // Instance methods. // ------------------------------------------------------------------------- - public List getPolicies() + public List<OID> getPolicies() { return policies; } - public List getPolicyQualifierInfos(OID oid) + /** + * Returns the list of policy OIDs, formatted as dotted-decimal strings. + * + * @return + */ + public List<String> getPolicyStrings() { - return (List) policyQualifierInfos.get(oid); + List<String> l = new ArrayList<String>(policies.size()); + for (OID oid : policies) + { + l.add(oid.toString()); + } + return l; } + public List<PolicyQualifierInfo> getPolicyQualifierInfos(OID oid) + { + return policyQualifierInfos.get(oid); + } + public byte[] getEncoded() { if (encoded == null) { - List pol = new ArrayList (policies.size()); - for (Iterator it = policies.iterator(); it.hasNext(); ) + List<DERValue> pol = new ArrayList<DERValue>(policies.size()); + for (Iterator<OID> it = policies.iterator(); it.hasNext(); ) { - OID policy = (OID) it.next(); - List qualifiers = getPolicyQualifierInfos (policy); - List l = new ArrayList (qualifiers == null ? 1 : 2); - l.add (new DERValue (DER.OBJECT_IDENTIFIER, policy)); + OID policy = it.next(); + List<PolicyQualifierInfo> qualifiers = getPolicyQualifierInfos(policy); + List<DERValue> l = new ArrayList<DERValue>(qualifiers == null ? 1 : 2); + l.add(new DERValue(DER.OBJECT_IDENTIFIER, policy)); if (qualifiers != null) { - List ll = new ArrayList (qualifiers.size()); - for (Iterator it2 = qualifiers.iterator(); it.hasNext(); ) + List<DERValue> ll = new ArrayList<DERValue>(qualifiers.size()); + for (Iterator<PolicyQualifierInfo> it2 = qualifiers.iterator(); it.hasNext(); ) { - PolicyQualifierInfo info = (PolicyQualifierInfo) it2.next(); + PolicyQualifierInfo info = it2.next(); try { - ll.add (DERReader.read (info.getEncoded())); + ll.add(DERReader.read(info.getEncoded())); } catch (IOException ioe) { } } - l.add (new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, ll)); + l.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, ll)); } - pol.add (new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, l)); + pol.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, l)); } - encoded = new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, pol).getEncoded(); + encoded = new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, pol).getEncoded(); } return (byte[]) encoded.clone(); } Modified: trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/ExtendedKeyUsage.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/ExtendedKeyUsage.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/ExtendedKeyUsage.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -1,5 +1,5 @@ /* ExtendedKeyUsage.java -- the extended key usage extension. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -56,7 +56,7 @@ public static final OID ID = new OID("2.5.29.37"); - private final List purposeIds; + private final List<OID> purposeIds; // Constructor. // ------------------------------------------------------------------------- @@ -69,13 +69,13 @@ if (!usageList.isConstructed()) throw new IOException("malformed ExtKeyUsageSyntax"); int len = 0; - purposeIds = new LinkedList(); + purposeIds = new LinkedList<OID>(); while (len < usageList.getLength()) { DERValue val = der.read(); if (val.getTag() != DER.OBJECT_IDENTIFIER) throw new IOException("malformed KeyPurposeId"); - purposeIds.add(val.getValue()); + purposeIds.add((OID) val.getValue()); len += val.getEncodedLength(); } } @@ -83,7 +83,7 @@ // Instance method. // ------------------------------------------------------------------------- - public List getPurposeIds() + public List<OID> getPurposeIds() { return Collections.unmodifiableList(purposeIds); } Modified: trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/Extension.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/Extension.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/Extension.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -1,5 +1,5 @@ /* Extension.java -- an X.509 certificate or CRL extension. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -171,6 +171,10 @@ { value = new ReasonCode(encval); } + else if (oid.equals(NameConstraints.ID)) + { + value = new NameConstraints(encval); + } else { value = new Value(encval); @@ -226,11 +230,11 @@ public DERValue getDerValue() { - List ext = new ArrayList (3); - ext.add (new DERValue (DER.OBJECT_IDENTIFIER, oid)); - ext.add (new DERValue (DER.BOOLEAN, Boolean.valueOf (critical))); - ext.add (new DERValue (DER.OCTET_STRING, value.getEncoded())); - return new DERValue (DER.CONSTRUCTED|DER.SEQUENCE, ext); + List<DERValue> ext = new ArrayList<DERValue>(3); + ext.add(new DERValue(DER.OBJECT_IDENTIFIER, oid)); + ext.add(new DERValue(DER.BOOLEAN, Boolean.valueOf(critical))); + ext.add(new DERValue(DER.OCTET_STRING, value.getEncoded())); + return new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, ext); } // Own methods. Modified: trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/GeneralNames.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/GeneralNames.java 2007-01-07 18:38:08 UTC (rev 3041) +++ trunk/core/src/classpath/gnu/gnu/java/security/x509/ext/GeneralNames.java 2007-01-07 18:39:36 UTC (rev 3042) @@ -38,106 +38,38 @@ package gnu.java.security.x509.ext; -import gnu.java.security.OID; -import gnu.java.security.der.DER; import gnu.java.security.der.DERReader; import gnu.java.security.der.DERValue; import java.io.IOException; -import java.net.InetAddress; -import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import javax.security.auth.x500.X500Principal; - public class GeneralNames { // Instance methods. // ------------------------------------------------------------------------- - public static final int OTHER_NAME = 0; - public static final int RFC822_NAME = 1; - public static final int DNS_NAME = 2; - public static final int X400_ADDRESS = 3; - public static final int DIRECTORY_NAME = 4; - public static final int EDI_PARTY_NAME = 5; - public static final int URI = 6; - public static final int IP_ADDRESS = 7; - public static final int REGISTERED_ID = 8; + private List<GeneralName> names; - private List names; - // Constructor. // ------------------------------------------------------------------------- public GeneralNames(final byte[] encoded) throws IOException { - names = new LinkedList(); + names = new LinkedList<GeneralName>(); DERReader der = new DERReader(encoded); DERValue nameList = der.read(); if (!nameList.isConstructed()) throw new IOException("malformed GeneralNames"); int len = 0; - int i = 0; while (len < nameList.getLength()) { DERValue name = der.read(); - List namePair = new ArrayList(2); - int tagClass = name.getTagClass(); - if (tagClass != DER.CONTEXT) - throw new IOException("malformed GeneralName: Tag class is " + tagClass); - namePair.add(Integer.valueOf(name.getTag())); - DERValue val = null; - switch (name.getTag()) - { - case RFC822_NAME: - case DNS_NAME: - case X400_ADDRESS: - case URI: - namePair.add(new String((byte[]) name.getValue())); - break; - - case OTHER_NAME: - // MUST return the encoded bytes of the OID/OctetString sequence - byte[] anotherName = name.getEncoded(); - anotherName[0] = (byte) (DER.CONSTRUCTED|DER.SEQUENCE); - namePair.add(anotherName); - // DERReader goes back on Constructed things so we need to skip over them - DERValue skip = der.read(); // skip OID - skip = der.read(); // skip Octet String - break; - - case EDI_PARTY_NAME: - namePair.add(name.getValue()); - break; - - case DIRECTORY_NAME: - byte[] b = name.getEncoded(); - b[0] = (byte) (DER.CONSTRUCTED|DER.SEQUENCE); - DERReader r = new DERReader (b); - r.read (); - namePair.add(new X500Principal(r.read ().getEncoded ()).toString()); - break; - - case IP_ADDRESS: - namePair.add(InetAddress.getByAddress((byte[]) name.getValue()) - .getHostAddress()); - break; - - case REGISTERED_ID: - byte[] bb = name.getEncoded(); - bb[0] = (byte) DER.OBJECT_IDENTIFIER; - namePair.add(new OID(bb).toString()); - break; - - default: - throw new IOException("unknown tag " + name.getTag()); - } - names.add(namePair); + GeneralName generalName = new GeneralName(name.getEncoded()); + names.add(generalName); len += name.getEncodedLength(); } } @@ -145,21 +77,9 @@ // Instance methods. // ------------------------------------------------------------------------- - public List getNames() - { - List l = new ArrayList(names.size()); - for (Iterator it = names.iterator(); it.hasNext(); ) + public List<GeneralName> getNames() { - List ll = (List) it.next(); - List pair = new ArrayList(2); - ... [truncated message content] |
From: <ls...@us...> - 2007-01-07 18:38:09
|
Revision: 3041 http://jnode.svn.sourceforge.net/jnode/?rev=3041&view=rev Author: lsantha Date: 2007-01-07 10:38:08 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/vm/gnu/java/lang/management/VMThreadMXBeanImpl.java Added Paths: ----------- trunk/core/src/classpath/vm/gnu/java/lang/management/VMOperatingSystemMXBeanImpl.java Added: trunk/core/src/classpath/vm/gnu/java/lang/management/VMOperatingSystemMXBeanImpl.java =================================================================== --- trunk/core/src/classpath/vm/gnu/java/lang/management/VMOperatingSystemMXBeanImpl.java (rev 0) +++ trunk/core/src/classpath/vm/gnu/java/lang/management/VMOperatingSystemMXBeanImpl.java 2007-01-07 18:38:08 UTC (rev 3041) @@ -0,0 +1,71 @@ +/* VMOperatingSystemMXBeanImpl.java - VM implementation of an OS bean + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.java.lang.management; + +import gnu.classpath.Configuration; + +/** + * Provides access to information about the operating system. + * + * @author Andrew John Hughes (gnu...@me...) + * @since 1.6 + */ +final class VMOperatingSystemMXBeanImpl +{ + + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("javalangmanagement"); + } + } + + /** + * Returns the system load average from the last + * minute. + * + * @return the system load average from the last + * minute. + */ + static double getSystemLoadAverage(){ + //todo implement it + throw new UnsupportedOperationException(); + } + +} Modified: trunk/core/src/classpath/vm/gnu/java/lang/management/VMThreadMXBeanImpl.java =================================================================== --- trunk/core/src/classpath/vm/gnu/java/lang/management/VMThreadMXBeanImpl.java 2007-01-07 16:10:30 UTC (rev 3040) +++ trunk/core/src/classpath/vm/gnu/java/lang/management/VMThreadMXBeanImpl.java 2007-01-07 18:38:08 UTC (rev 3041) @@ -43,7 +43,7 @@ * Provides access to information about the threads * of the virtual machine. An instance of this bean is * obtained by calling - * {@link ManagementFactory#getThreadMXBean()}. + * {@link java.lang.management.ManagementFactory#getThreadMXBean()}. * See {@link java.lang.management.ThreadMXBean} for * full documentation. * @@ -60,6 +60,19 @@ /** * Returns the ids of cycles of deadlocked threads, occurring + * due to monitor ownership or ownable synchronizer ownership. + * This will only be called if ownable synchronizer monitoring + * is supported. + * + * @return the ids of the deadlocked threads. + */ + static long[] findDeadlockedThreads(){ + //todo implement + throw new UnsupportedOperationException(); + } + + /** + * Returns the ids of cycles of deadlocked threads, occurring * due to monitor ownership. * * @return the ids of the deadlocked threads. @@ -144,6 +157,31 @@ } /** + * Fill out the given {@link ThreadInfo} object + * with ownable synchronizer usage information. + * This is only called if ownable synchronizer + * usage monitoring is supported. + * + * @param info the {@link ThreadInfo} object to modify. + */ + static void getLockInfo(ThreadInfo info){ + //todo implement + throw new UnsupportedOperationException(); + } + + /** + * Fill out the given {@link ThreadInfo} object + * with monitor usage information. This is only + * called if monitor usage monitoring is supported. + * + * @param info the {@link ThreadInfo} object to modify. + */ + static void getMonitorInfo(ThreadInfo info){ + //todo implement + throw new UnsupportedOperationException(); + } + + /** * Returns the current peak number of live threads. * * @return the peak number of live threads. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-07 16:10:34
|
Revision: 3040 http://jnode.svn.sourceforge.net/jnode/?rev=3040&view=rev Author: lsantha Date: 2007-01-07 08:10:30 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Added rmic templates. Modified Paths: -------------- trunk/core/build.xml Modified: trunk/core/build.xml =================================================================== --- trunk/core/build.xml 2007-01-07 16:09:10 UTC (rev 3039) +++ trunk/core/build.xml 2007-01-07 16:10:30 UTC (rev 3040) @@ -91,6 +91,7 @@ <fileset dir="${my-src.dir}/classpath/gnu" includes="**/*.properties"/> <fileset dir="${my-src.dir}/classpath/java" includes="**/*.properties"/> <fileset dir="${my-src.dir}/classpath/vm" includes="**/*.security"/> + <fileset dir="${my-src.dir}/classpath/tools" includes="**/*.jav"/> </copy> <ExpandTest classname="PrimitiveIntTest" type="int"/> <ExpandTest classname="PrimitiveLongTest" type="long"/> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-07 16:09:12
|
Revision: 3039 http://jnode.svn.sourceforge.net/jnode/?rev=3039&view=rev Author: lsantha Date: 2007-01-07 08:09:10 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Added rmic templates. Modified Paths: -------------- trunk/core/descriptors/org.classpath.tools.xml Modified: trunk/core/descriptors/org.classpath.tools.xml =================================================================== --- trunk/core/descriptors/org.classpath.tools.xml 2007-01-07 14:11:30 UTC (rev 3038) +++ trunk/core/descriptors/org.classpath.tools.xml 2007-01-07 16:09:10 UTC (rev 3039) @@ -24,6 +24,7 @@ <export name="gnu.classpath.tools.rmid.*"/> <export name="gnu.classpath.tools.rmiregistry.*"/> <export name="gnu.classpath.tools.rmic.*"/> + <export name="gnu.classpath.tools.rmic.templates.*"/> <export name="gnu.classpath.tools.serialver.*"/> <export name="gnu.classpath.tools.tnameserv.*"/> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-07 14:11:31
|
Revision: 3038 http://jnode.svn.sourceforge.net/jnode/?rev=3038&view=rev Author: lsantha Date: 2007-01-07 06:11:30 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Added rmic. Modified Paths: -------------- trunk/core/descriptors/org.classpath.tools.xml Modified: trunk/core/descriptors/org.classpath.tools.xml =================================================================== --- trunk/core/descriptors/org.classpath.tools.xml 2007-01-07 13:59:33 UTC (rev 3037) +++ trunk/core/descriptors/org.classpath.tools.xml 2007-01-07 14:11:30 UTC (rev 3038) @@ -12,7 +12,6 @@ <runtime> <library name="jnode-core.jar"> - <export name="gnu.classpath.tools.*"/> <export name="gnu.classpath.tools.appletviewer.*"/> <export name="gnu.classpath.tools.common.*"/> @@ -24,10 +23,20 @@ <export name="gnu.classpath.tools.orbd.*"/> <export name="gnu.classpath.tools.rmid.*"/> <export name="gnu.classpath.tools.rmiregistry.*"/> - <!--export name="gnu.classpath.tools.rmic.*"/--> + <export name="gnu.classpath.tools.rmic.*"/> <export name="gnu.classpath.tools.serialver.*"/> <export name="gnu.classpath.tools.tnameserv.*"/> + <export name="org.objectweb.asm.*"/> + <export name="org.objectweb.asm.attrs.*"/> + <export name="org.objectweb.asm.commons.*"/> + <export name="org.objectweb.asm.optimizer.*"/> + <export name="org.objectweb.asm.signature.*"/> + <export name="org.objectweb.asm.tree.*"/> + <export name="org.objectweb.asm.tree.analysis.*"/> + <export name="org.objectweb.asm.util.*"/> + <export name="org.objectweb.asm.util.attrs.*"/> + <export name="org.objectweb.asm.xml.*"/> </library> </runtime> @@ -38,7 +47,7 @@ <alias name="keytool" class="gnu.classpath.tools.keytool.Main"/> <alias name="native2ascii" class="gnu.classpath.tools.native2ascii.Native2ASCII"/> <alias name="orbd" class="gnu.classpath.tools.orbd.Main"/> - <!--alias name="rmic" class="gnu.classpath.tools.rmi.RMIC"/--> + <alias name="rmic" class="gnu.classpath.tools.rmic.Main"/> <alias name="rmid" class="gnu.classpath.tools.rmid.Main"/> <alias name="rmiregistry" class="gnu.classpath.tools.rmiregistry.Main"/> <alias name="serialver" class="gnu.classpath.tools.serialver.SerialVer"/> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-07 13:59:34
|
Revision: 3037 http://jnode.svn.sourceforge.net/jnode/?rev=3037&view=rev Author: lsantha Date: 2007-01-07 05:59:33 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/all/build.xml Modified: trunk/all/build.xml =================================================================== --- trunk/all/build.xml 2007-01-07 13:58:42 UTC (rev 3036) +++ trunk/all/build.xml 2007-01-07 13:59:33 UTC (rev 3037) @@ -517,6 +517,10 @@ <patternset refid="cp-includes-pattern"/> <patternset refid="cp-sources-pattern"/> </fileset> + <fileset dir="${root.dir}/../classpath/tools/external/asm"> + <patternset refid="cp-includes-pattern"/> + <patternset refid="cp-sources-pattern"/> + </fileset> </classpathsources> </cp-compare> </target> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-07 13:58:43
|
Revision: 3036 http://jnode.svn.sourceforge.net/jnode/?rev=3036&view=rev Author: lsantha Date: 2007-01-07 05:58:42 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Added Paths: ----------- trunk/core/src/classpath/org/org/objectweb/asm/AnnotationVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/AnnotationWriter.java trunk/core/src/classpath/org/org/objectweb/asm/Attribute.java trunk/core/src/classpath/org/org/objectweb/asm/ByteVector.java trunk/core/src/classpath/org/org/objectweb/asm/ClassAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/ClassReader.java trunk/core/src/classpath/org/org/objectweb/asm/ClassVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/ClassWriter.java trunk/core/src/classpath/org/org/objectweb/asm/Edge.java trunk/core/src/classpath/org/org/objectweb/asm/FieldVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/FieldWriter.java trunk/core/src/classpath/org/org/objectweb/asm/Handler.java trunk/core/src/classpath/org/org/objectweb/asm/Item.java trunk/core/src/classpath/org/org/objectweb/asm/Label.java trunk/core/src/classpath/org/org/objectweb/asm/MethodAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/MethodVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/MethodWriter.java trunk/core/src/classpath/org/org/objectweb/asm/Opcodes.java trunk/core/src/classpath/org/org/objectweb/asm/Type.java trunk/core/src/classpath/org/org/objectweb/asm/package.html Added: trunk/core/src/classpath/org/org/objectweb/asm/AnnotationVisitor.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/AnnotationVisitor.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/AnnotationVisitor.java 2007-01-07 13:58:42 UTC (rev 3036) @@ -0,0 +1,88 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm; + +/** + * A visitor to visit a Java annotation. The methods of this interface must be + * called in the following order: (<tt>visit<tt> | <tt>visitEnum<tt> | + * <tt>visitAnnotation<tt> | <tt>visitArray<tt>)* <tt>visitEnd<tt>. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public interface AnnotationVisitor { + + /** + * Visits a primitive value of the annotation. + * + * @param name the value name. + * @param value the actual value, whose type must be {@link Byte}, + * {@link Boolean}, {@link Character}, {@link Short}, + * {@link Integer}, {@link Long}, {@link Float}, {@link Double}, + * {@link String} or {@link Type}. + */ + void visit(String name, Object value); + + /** + * Visits an enumeration value of the annotation. + * + * @param name the value name. + * @param desc the class descriptor of the enumeration class. + * @param value the actual enumeration value. + */ + void visitEnum(String name, String desc, String value); + + /** + * Visits a nested annotation value of the annotation. + * + * @param name the value name. + * @param desc the class descriptor of the nested annotation class. + * @return a non null visitor to visit the actual nested annotation value. + * <i>The nested annotation value must be fully visited before + * calling other methods on this annotation visitor</i>. + */ + AnnotationVisitor visitAnnotation(String name, String desc); + + /** + * Visits an array value of the annotation. + * + * @param name the value name. + * @return a non null visitor to visit the actual array value elements. The + * 'name' parameters passed to the methods of this visitor are + * ignored. <i>All the array values must be visited before calling + * other methods on this annotation visitor</i>. + */ + AnnotationVisitor visitArray(String name); + + /** + * Visits the end of the annotation. + */ + void visitEnd(); +} Added: trunk/core/src/classpath/org/org/objectweb/asm/AnnotationWriter.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/AnnotationWriter.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/AnnotationWriter.java 2007-01-07 13:58:42 UTC (rev 3036) @@ -0,0 +1,311 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm; + +/** + * An {@link AnnotationVisitor} that generates annotations in bytecode form. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +final class AnnotationWriter implements AnnotationVisitor { + + /** + * The class writer to which this annotation must be added. + */ + private final ClassWriter cw; + + /** + * The number of values in this annotation. + */ + private int size; + + /** + * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation + * writers used for annotation default and annotation arrays use unnamed + * values. + */ + private final boolean named; + + /** + * The annotation values in bytecode form. This byte vector only contains + * the values themselves, i.e. the number of values must be stored as a + * unsigned short just before these bytes. + */ + private final ByteVector bv; + + /** + * The byte vector to be used to store the number of values of this + * annotation. See {@link #bv}. + */ + private final ByteVector parent; + + /** + * Where the number of values of this annotation must be stored in + * {@link #parent}. + */ + private final int offset; + + /** + * Next annotation writer. This field is used to store annotation lists. + */ + AnnotationWriter next; + + /** + * Previous annotation writer. This field is used to store annotation lists. + */ + AnnotationWriter prev; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link AnnotationWriter}. + * + * @param cw the class writer to which this annotation must be added. + * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise. + * @param bv where the annotation values must be stored. + * @param parent where the number of annotation values must be stored. + * @param offset where in <tt>parent</tt> the number of annotation values must + * be stored. + */ + AnnotationWriter( + final ClassWriter cw, + final boolean named, + final ByteVector bv, + final ByteVector parent, + final int offset) + { + this.cw = cw; + this.named = named; + this.bv = bv; + this.parent = parent; + this.offset = offset; + } + + // ------------------------------------------------------------------------ + // Implementation of the AnnotationVisitor interface + // ------------------------------------------------------------------------ + + public void visit(final String name, final Object value) { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + if (value instanceof String) { + bv.put12('s', cw.newUTF8((String) value)); + } else if (value instanceof Byte) { + bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); + } else if (value instanceof Boolean) { + int v = ((Boolean) value).booleanValue() ? 1 : 0; + bv.put12('Z', cw.newInteger(v).index); + } else if (value instanceof Character) { + bv.put12('C', cw.newInteger(((Character) value).charValue()).index); + } else if (value instanceof Short) { + bv.put12('S', cw.newInteger(((Short) value).shortValue()).index); + } else if (value instanceof Type) { + bv.put12('c', cw.newUTF8(((Type) value).getDescriptor())); + } else if (value instanceof byte[]) { + byte[] v = (byte[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('B', cw.newInteger(v[i]).index); + } + } else if (value instanceof boolean[]) { + boolean[] v = (boolean[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index); + } + } else if (value instanceof short[]) { + short[] v = (short[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('S', cw.newInteger(v[i]).index); + } + } else if (value instanceof char[]) { + char[] v = (char[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('C', cw.newInteger(v[i]).index); + } + } else if (value instanceof int[]) { + int[] v = (int[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('I', cw.newInteger(v[i]).index); + } + } else if (value instanceof long[]) { + long[] v = (long[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('J', cw.newLong(v[i]).index); + } + } else if (value instanceof float[]) { + float[] v = (float[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('F', cw.newFloat(v[i]).index); + } + } else if (value instanceof double[]) { + double[] v = (double[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('D', cw.newDouble(v[i]).index); + } + } else { + Item i = cw.newConstItem(value); + bv.put12(".s.IFJDCS".charAt(i.type), i.index); + } + } + + public void visitEnum( + final String name, + final String desc, + final String value) + { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); + } + + public AnnotationVisitor visitAnnotation( + final String name, + final String desc) + { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + // write tag and type, and reserve space for values count + bv.put12('@', cw.newUTF8(desc)).putShort(0); + return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); + } + + public AnnotationVisitor visitArray(final String name) { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + // write tag, and reserve space for array size + bv.put12('[', 0); + return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); + } + + public void visitEnd() { + if (parent != null) { + byte[] data = parent.data; + data[offset] = (byte) (size >>> 8); + data[offset + 1] = (byte) size; + } + } + + // ------------------------------------------------------------------------ + // Utility methods + // ------------------------------------------------------------------------ + + /** + * Returns the size of this annotation writer list. + * + * @return the size of this annotation writer list. + */ + int getSize() { + int size = 0; + AnnotationWriter aw = this; + while (aw != null) { + size += aw.bv.length; + aw = aw.next; + } + return size; + } + + /** + * Puts the annotations of this annotation writer list into the given byte + * vector. + * + * @param out where the annotations must be put. + */ + void put(final ByteVector out) { + int n = 0; + int size = 2; + AnnotationWriter aw = this; + AnnotationWriter last = null; + while (aw != null) { + ++n; + size += aw.bv.length; + aw.visitEnd(); // in case user forgot to call visitEnd + aw.prev = last; + last = aw; + aw = aw.next; + } + out.putInt(size); + out.putShort(n); + aw = last; + while (aw != null) { + out.putByteArray(aw.bv.data, 0, aw.bv.length); + aw = aw.prev; + } + } + + /** + * Puts the given annotation lists into the given byte vector. + * + * @param panns an array of annotation writer lists. + * @param out where the annotations must be put. + */ + static void put(final AnnotationWriter[] panns, final ByteVector out) { + int size = 1 + 2 * panns.length; + for (int i = 0; i < panns.length; ++i) { + size += panns[i] == null ? 0 : panns[i].getSize(); + } + out.putInt(size).putByte(panns.length); + for (int i = 0; i < panns.length; ++i) { + AnnotationWriter aw = panns[i]; + AnnotationWriter last = null; + int n = 0; + while (aw != null) { + ++n; + aw.visitEnd(); // in case user forgot to call visitEnd + aw.prev = last; + last = aw; + aw = aw.next; + } + out.putShort(n); + aw = last; + while (aw != null) { + out.putByteArray(aw.bv.data, 0, aw.bv.length); + aw = aw.prev; + } + } + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/Attribute.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/Attribute.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/Attribute.java 2007-01-07 13:58:42 UTC (rev 3036) @@ -0,0 +1,254 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm; + +/** + * A non standard class, field, method or code attribute. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public class Attribute { + + /** + * The type of this attribute. + */ + public final String type; + + /** + * The raw value of this attribute, used only for unknown attributes. + */ + byte[] value; + + /** + * The next attribute in this attribute list. May be <tt>null</tt>. + */ + Attribute next; + + /** + * Constructs a new empty attribute. + * + * @param type the type of the attribute. + */ + protected Attribute(final String type) { + this.type = type; + } + + /** + * Returns <tt>true</tt> if this type of attribute is unknown. The default + * implementation of this method always returns <tt>true</tt>. + * + * @return <tt>true</tt> if this type of attribute is unknown. + */ + public boolean isUnknown() { + return true; + } + + /** + * Returns <tt>true</tt> if this type of attribute is a code attribute. + * + * @return <tt>true</tt> if this type of attribute is a code attribute. + */ + public boolean isCodeAttribute() { + return false; + } + + /** + * Returns the labels corresponding to this attribute. + * + * @return the labels corresponding to this attribute, or <tt>null</tt> if + * this attribute is not a code attribute that contains labels. + */ + protected Label[] getLabels() { + return null; + } + + /** + * Reads a {@link #type type} attribute. This method must return a <i>new</i> + * {@link Attribute} object, of type {@link #type type}, corresponding to + * the <tt>len</tt> bytes starting at the given offset, in the given class + * reader. + * + * @param cr the class that contains the attribute to be read. + * @param off index of the first byte of the attribute's content in {@link + * ClassReader#b cr.b}. The 6 attribute header bytes, containing the + * type and the length of the attribute, are not taken into account + * here. + * @param len the length of the attribute's content. + * @param buf buffer to be used to call + * {@link ClassReader#readUTF8 readUTF8}, + * {@link ClassReader#readClass(int,char[]) readClass} or + * {@link ClassReader#readConst readConst}. + * @param codeOff index of the first byte of code's attribute content in + * {@link ClassReader#b cr.b}, or -1 if the attribute to be read is + * not a code attribute. The 6 attribute header bytes, containing the + * type and the length of the attribute, are not taken into account + * here. + * @param labels the labels of the method's code, or <tt>null</tt> if the + * attribute to be read is not a code attribute. + * @return a <i>new</i> {@link Attribute} object corresponding to the given + * bytes. + */ + protected Attribute read( + ClassReader cr, + int off, + int len, + char[] buf, + int codeOff, + Label[] labels) + { + Attribute attr = new Attribute(type); + attr.value = new byte[len]; + System.arraycopy(cr.b, off, attr.value, 0, len); + return attr; + } + + /** + * Returns the byte array form of this attribute. + * + * @param cw the class to which this attribute must be added. This parameter + * can be used to add to the constant pool of this class the items + * that corresponds to this attribute. + * @param code the bytecode of the method corresponding to this code + * attribute, or <tt>null</tt> if this attribute is not a code + * attributes. + * @param len the length of the bytecode of the method corresponding to this + * code attribute, or <tt>null</tt> if this attribute is not a code + * attribute. + * @param maxStack the maximum stack size of the method corresponding to + * this code attribute, or -1 if this attribute is not a code + * attribute. + * @param maxLocals the maximum number of local variables of the method + * corresponding to this code attribute, or -1 if this attribute is + * not a code attribute. + * @return the byte array form of this attribute. + */ + protected ByteVector write( + ClassWriter cw, + byte[] code, + int len, + int maxStack, + int maxLocals) + { + ByteVector v = new ByteVector(); + v.data = value; + v.length = value.length; + return v; + } + + /** + * Returns the length of the attribute list that begins with this attribute. + * + * @return the length of the attribute list that begins with this attribute. + */ + final int getCount() { + int count = 0; + Attribute attr = this; + while (attr != null) { + count += 1; + attr = attr.next; + } + return count; + } + + /** + * Returns the size of all the attributes in this attribute list. + * + * @param cw the class writer to be used to convert the attributes into byte + * arrays, with the {@link #write write} method. + * @param code the bytecode of the method corresponding to these code + * attributes, or <tt>null</tt> if these attributes are not code + * attributes. + * @param len the length of the bytecode of the method corresponding to + * these code attributes, or <tt>null</tt> if these attributes are + * not code attributes. + * @param maxStack the maximum stack size of the method corresponding to + * these code attributes, or -1 if these attributes are not code + * attributes. + * @param maxLocals the maximum number of local variables of the method + * corresponding to these code attributes, or -1 if these attributes + * are not code attributes. + * @return the size of all the attributes in this attribute list. This size + * includes the size of the attribute headers. + */ + final int getSize( + final ClassWriter cw, + final byte[] code, + final int len, + final int maxStack, + final int maxLocals) + { + Attribute attr = this; + int size = 0; + while (attr != null) { + cw.newUTF8(attr.type); + size += attr.write(cw, code, len, maxStack, maxLocals).length + 6; + attr = attr.next; + } + return size; + } + + /** + * Writes all the attributes of this attribute list in the given byte + * vector. + * + * @param cw the class writer to be used to convert the attributes into byte + * arrays, with the {@link #write write} method. + * @param code the bytecode of the method corresponding to these code + * attributes, or <tt>null</tt> if these attributes are not code + * attributes. + * @param len the length of the bytecode of the method corresponding to + * these code attributes, or <tt>null</tt> if these attributes are + * not code attributes. + * @param maxStack the maximum stack size of the method corresponding to + * these code attributes, or -1 if these attributes are not code + * attributes. + * @param maxLocals the maximum number of local variables of the method + * corresponding to these code attributes, or -1 if these attributes + * are not code attributes. + * @param out where the attributes must be written. + */ + final void put( + final ClassWriter cw, + final byte[] code, + final int len, + final int maxStack, + final int maxLocals, + final ByteVector out) + { + Attribute attr = this; + while (attr != null) { + ByteVector b = attr.write(cw, code, len, maxStack, maxLocals); + out.putShort(cw.newUTF8(attr.type)).putInt(b.length); + out.putByteArray(b.data, 0, b.length); + attr = attr.next; + } + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/ByteVector.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/ByteVector.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/ByteVector.java 2007-01-07 13:58:42 UTC (rev 3036) @@ -0,0 +1,293 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm; + +/** + * A dynamically extensible vector of bytes. This class is roughly equivalent to + * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient. + * + * @author Eric Bruneton + */ +public class ByteVector { + + /** + * The content of this vector. + */ + byte[] data; + + /** + * Actual number of bytes in this vector. + */ + int length; + + /** + * Constructs a new {@link ByteVector ByteVector} with a default initial + * size. + */ + public ByteVector() { + data = new byte[64]; + } + + /** + * Constructs a new {@link ByteVector ByteVector} with the given initial + * size. + * + * @param initialSize the initial size of the byte vector to be constructed. + */ + public ByteVector(final int initialSize) { + data = new byte[initialSize]; + } + + /** + * Puts a byte into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param b a byte. + * @return this byte vector. + */ + public ByteVector putByte(final int b) { + int length = this.length; + if (length + 1 > data.length) { + enlarge(1); + } + data[length++] = (byte) b; + this.length = length; + return this; + } + + /** + * Puts two bytes into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param b1 a byte. + * @param b2 another byte. + * @return this byte vector. + */ + ByteVector put11(final int b1, final int b2) { + int length = this.length; + if (length + 2 > data.length) { + enlarge(2); + } + byte[] data = this.data; + data[length++] = (byte) b1; + data[length++] = (byte) b2; + this.length = length; + return this; + } + + /** + * Puts a short into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param s a short. + * @return this byte vector. + */ + public ByteVector putShort(final int s) { + int length = this.length; + if (length + 2 > data.length) { + enlarge(2); + } + byte[] data = this.data; + data[length++] = (byte) (s >>> 8); + data[length++] = (byte) s; + this.length = length; + return this; + } + + /** + * Puts a byte and a short into this byte vector. The byte vector is + * automatically enlarged if necessary. + * + * @param b a byte. + * @param s a short. + * @return this byte vector. + */ + ByteVector put12(final int b, final int s) { + int length = this.length; + if (length + 3 > data.length) { + enlarge(3); + } + byte[] data = this.data; + data[length++] = (byte) b; + data[length++] = (byte) (s >>> 8); + data[length++] = (byte) s; + this.length = length; + return this; + } + + /** + * Puts an int into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param i an int. + * @return this byte vector. + */ + public ByteVector putInt(final int i) { + int length = this.length; + if (length + 4 > data.length) { + enlarge(4); + } + byte[] data = this.data; + data[length++] = (byte) (i >>> 24); + data[length++] = (byte) (i >>> 16); + data[length++] = (byte) (i >>> 8); + data[length++] = (byte) i; + this.length = length; + return this; + } + + /** + * Puts a long into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param l a long. + * @return this byte vector. + */ + public ByteVector putLong(final long l) { + int length = this.length; + if (length + 8 > data.length) { + enlarge(8); + } + byte[] data = this.data; + int i = (int) (l >>> 32); + data[length++] = (byte) (i >>> 24); + data[length++] = (byte) (i >>> 16); + data[length++] = (byte) (i >>> 8); + data[length++] = (byte) i; + i = (int) l; + data[length++] = (byte) (i >>> 24); + data[length++] = (byte) (i >>> 16); + data[length++] = (byte) (i >>> 8); + data[length++] = (byte) i; + this.length = length; + return this; + } + + /** + * Puts an UTF8 string into this byte vector. The byte vector is + * automatically enlarged if necessary. + * + * @param s a String. + * @return this byte vector. + */ + public ByteVector putUTF8(final String s) { + int charLength = s.length(); + if (length + 2 + charLength > data.length) { + enlarge(2 + charLength); + } + int len = length; + byte[] data = this.data; + // optimistic algorithm: instead of computing the byte length and then + // serializing the string (which requires two loops), we assume the byte + // length is equal to char length (which is the most frequent case), and + // we start serializing the string right away. During the serialization, + // if we find that this assumption is wrong, we continue with the + // general method. + data[len++] = (byte) (charLength >>> 8); + data[len++] = (byte) (charLength); + for (int i = 0; i < charLength; ++i) { + char c = s.charAt(i); + if (c >= '\001' && c <= '\177') { + data[len++] = (byte) c; + } else { + int byteLength = i; + for (int j = i; j < charLength; ++j) { + c = s.charAt(j); + if (c >= '\001' && c <= '\177') { + byteLength++; + } else if (c > '\u07FF') { + byteLength += 3; + } else { + byteLength += 2; + } + } + data[length] = (byte) (byteLength >>> 8); + data[length + 1] = (byte) (byteLength); + if (length + 2 + byteLength > data.length) { + length = len; + enlarge(2 + byteLength); + data = this.data; + } + for (int j = i; j < charLength; ++j) { + c = s.charAt(j); + if (c >= '\001' && c <= '\177') { + data[len++] = (byte) c; + } else if (c > '\u07FF') { + data[len++] = (byte) (0xE0 | c >> 12 & 0xF); + data[len++] = (byte) (0x80 | c >> 6 & 0x3F); + data[len++] = (byte) (0x80 | c & 0x3F); + } else { + data[len++] = (byte) (0xC0 | c >> 6 & 0x1F); + data[len++] = (byte) (0x80 | c & 0x3F); + } + } + break; + } + } + length = len; + return this; + } + + /** + * Puts an array of bytes into this byte vector. The byte vector is + * automatically enlarged if necessary. + * + * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt> + * null bytes into this byte vector. + * @param off index of the fist byte of b that must be copied. + * @param len number of bytes of b that must be copied. + * @return this byte vector. + */ + public ByteVector putByteArray(final byte[] b, final int off, final int len) + { + if (length + len > data.length) { + enlarge(len); + } + if (b != null) { + System.arraycopy(b, off, data, length, len); + } + length += len; + return this; + } + + /** + * Enlarge this byte vector so that it can receive n more bytes. + * + * @param size number of additional bytes that this byte vector should be + * able to receive. + */ + private void enlarge(final int size) { + int length1 = 2 * data.length; + int length2 = length + size; + byte[] newData = new byte[length1 > length2 ? length1 : length2]; + System.arraycopy(data, 0, newData, 0, length); + data = newData; + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/ClassAdapter.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/ClassAdapter.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/ClassAdapter.java 2007-01-07 13:58:42 UTC (rev 3036) @@ -0,0 +1,121 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm; + +/** + * An empty {@link ClassVisitor} that delegates to another {@link ClassVisitor}. + * This class can be used as a super class to quickly implement usefull class + * adapter classes, just by overriding the necessary methods. + * + * @author Eric Bruneton + */ +public class ClassAdapter implements ClassVisitor { + + /** + * The {@link ClassVisitor} to which this adapter delegates calls. + */ + protected ClassVisitor cv; + + /** + * Constructs a new {@link ClassAdapter} object. + * + * @param cv the class visitor to which this adapter must delegate calls. + */ + public ClassAdapter(final ClassVisitor cv) { + this.cv = cv; + } + + public void visit( + final int version, + final int access, + final String name, + final String signature, + final String superName, + final String[] interfaces) + { + cv.visit(version, access, name, signature, superName, interfaces); + } + + public void visitSource(final String source, final String debug) { + cv.visitSource(source, debug); + } + + public void visitOuterClass( + final String owner, + final String name, + final String desc) + { + cv.visitOuterClass(owner, name, desc); + } + + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + return cv.visitAnnotation(desc, visible); + } + + public void visitAttribute(final Attribute attr) { + cv.visitAttribute(attr); + } + + public void visitInnerClass( + final String name, + final String outerName, + final String innerName, + final int access) + { + cv.visitInnerClass(name, outerName, innerName, access); + } + + public FieldVisitor visitField( + final int access, + final String name, + final String desc, + final String signature, + final Object value) + { + return cv.visitField(access, name, desc, signature, value); + } + + public MethodVisitor visitMethod( + final int access, + final String name, + final String desc, + final String signature, + final String[] exceptions) + { + return cv.visitMethod(access, name, desc, signature, exceptions); + } + + public void visitEnd() { + cv.visitEnd(); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/ClassReader.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/ClassReader.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/ClassReader.java 2007-01-07 13:58:42 UTC (rev 3036) @@ -0,0 +1,1606 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm; + +import java.io.InputStream; +import java.io.IOException; + +/** + * A Java class parser to make a {@link ClassVisitor} visit an existing class. + * This class parses a byte array conforming to the Java class file format and + * calls the appropriate visit methods of a given class visitor for each field, + * method and bytecode instruction encountered. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public class ClassReader { + + /** + * The class to be parsed. <i>The content of this array must not be + * modified. This field is intended for {@link Attribute} sub classes, and + * is normally not needed by class generators or adapters.</i> + */ + public final byte[] b; + + /** + * The start index of each constant pool item in {@link #b b}, plus one. + * The one byte offset skips the constant pool item tag that indicates its + * type. + */ + private int[] items; + + /** + * The String objects corresponding to the CONSTANT_Utf8 items. This cache + * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item, + * which GREATLY improves performances (by a factor 2 to 3). This caching + * strategy could be extended to all constant pool items, but its benefit + * would not be so great for these items (because they are much less + * expensive to parse than CONSTANT_Utf8 items). + */ + private String[] strings; + + /** + * Maximum length of the strings contained in the constant pool of the + * class. + */ + private int maxStringLength; + + /** + * Start index of the class header information (access, name...) in + * {@link #b b}. + */ + public final int header; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link ClassReader} object. + * + * @param b the bytecode of the class to be read. + */ + public ClassReader(final byte[] b) { + this(b, 0, b.length); + } + + /** + * Constructs a new {@link ClassReader} object. + * + * @param b the bytecode of the class to be read. + * @param off the start offset of the class data. + * @param len the length of the class data. + */ + public ClassReader(final byte[] b, final int off, final int len) { + this.b = b; + // parses the constant pool + items = new int[readUnsignedShort(off + 8)]; + int ll = items.length; + strings = new String[ll]; + int max = 0; + int index = off + 10; + for (int i = 1; i < ll; ++i) { + items[i] = index + 1; + int tag = b[index]; + int size; + switch (tag) { + case ClassWriter.FIELD: + case ClassWriter.METH: + case ClassWriter.IMETH: + case ClassWriter.INT: + case ClassWriter.FLOAT: + case ClassWriter.NAME_TYPE: + size = 5; + break; + case ClassWriter.LONG: + case ClassWriter.DOUBLE: + size = 9; + ++i; + break; + case ClassWriter.UTF8: + size = 3 + readUnsignedShort(index + 1); + if (size > max) { + max = size; + } + break; + // case ClassWriter.CLASS: + // case ClassWriter.STR: + default: + size = 3; + break; + } + index += size; + } + maxStringLength = max; + // the class header information starts just after the constant pool + header = index; + } + + /** + * Copies the constant pool data into the given {@link ClassWriter}. Should + * be called before the {@link #accept(ClassVisitor,boolean)} method. + * + * @param classWriter the {@link ClassWriter} to copy constant pool into. + */ + void copyPool(final ClassWriter classWriter) { + char[] buf = new char[maxStringLength]; + int ll = items.length; + Item[] items2 = new Item[ll]; + for (int i = 1; i < ll; i++) { + int index = items[i]; + int tag = b[index - 1]; + Item item = new Item(i); + int nameType; + switch (tag) { + case ClassWriter.FIELD: + case ClassWriter.METH: + case ClassWriter.IMETH: + nameType = items[readUnsignedShort(index + 2)]; + item.set(tag, + readClass(index, buf), + readUTF8(nameType, buf), + readUTF8(nameType + 2, buf)); + break; + + case ClassWriter.INT: + item.set(readInt(index)); + break; + + case ClassWriter.FLOAT: + item.set(Float.intBitsToFloat(readInt(index))); + break; + + case ClassWriter.NAME_TYPE: + item.set(tag, + readUTF8(index, buf), + readUTF8(index + 2, buf), + null); + break; + + case ClassWriter.LONG: + item.set(readLong(index)); + ++i; + break; + + case ClassWriter.DOUBLE: + item.set(Double.longBitsToDouble(readLong(index))); + ++i; + break; + + case ClassWriter.UTF8: { + String s = strings[i]; + if (s == null) { + index = items[i]; + s = strings[i] = readUTF(index + 2, + readUnsignedShort(index), + buf); + } + item.set(tag, s, null, null); + } + break; + + // case ClassWriter.STR: + // case ClassWriter.CLASS: + default: + item.set(tag, readUTF8(index, buf), null, null); + break; + } + + int index2 = item.hashCode % items2.length; + item.next = items2[index2]; + items2[index2] = item; + } + + int off = items[1] - 1; + classWriter.pool.putByteArray(b, off, header - off); + classWriter.items = items2; + classWriter.threshold = (int) (0.75d * ll); + classWriter.index = ll; + } + + /** + * Constructs a new {@link ClassReader} object. + * + * @param is an input stream from which to read the class. + * @throws IOException if a problem occurs during reading. + */ + public ClassReader(final InputStream is) throws IOException { + this(readClass(is)); + } + + /** + * Constructs a new {@link ClassReader} object. + * + * @param name the fully qualified name of the class to be read. + * @throws IOException if an exception occurs during reading. + */ + public ClassReader(final String name) throws IOException { + this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/') + + ".class")); + } + + /** + * Reads the bytecode of a class. + * + * @param is an input stream from which to read the class. + * @return the bytecode read from the given input stream. + * @throws IOException if a problem occurs during reading. + */ + private static byte[] readClass(final InputStream is) throws IOException { + if (is == null) { + throw new IOException("Class not found"); + } + byte[] b = new byte[is.available()]; + int len = 0; + while (true) { + int n = is.read(b, len, b.length - len); + if (n == -1) { + if (len < b.length) { + byte[] c = new byte[len]; + System.arraycopy(b, 0, c, 0, len); + b = c; + } + return b; + } + len += n; + if (len == b.length) { + byte[] c = new byte[b.length + 1000]; + System.arraycopy(b, 0, c, 0, len); + b = c; + } + } + } + + // ------------------------------------------------------------------------ + // Public methods + // ------------------------------------------------------------------------ + + /** + * Makes the given visitor visit the Java class of this {@link ClassReader}. + * This class is the one specified in the constructor (see + * {@link #ClassReader(byte[]) ClassReader}). + * + * @param classVisitor the visitor that must visit this class. + * @param skipDebug <tt>true</tt> if the debug information of the class + * must not be visited. In this case the + * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and + * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will + * not be called. + */ + public void accept(final ClassVisitor classVisitor, final boolean skipDebug) + { + accept(classVisitor, new Attribute[0], skipDebug); + } + + /** + * Makes the given visitor visit the Java class of this {@link ClassReader}. + * This class is the one specified in the constructor (see + * {@link #ClassReader(byte[]) ClassReader}). + * + * @param classVisitor the visitor that must visit this class. + * @param attrs prototypes of the attributes that must be parsed during the + * visit of the class. Any attribute whose type is not equal to the + * type of one the prototypes will be ignored. + * @param skipDebug <tt>true</tt> if the debug information of the class + * must not be visited. In this case the + * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and + * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will + * not be called. + */ + public void accept( + final ClassVisitor classVisitor, + final Attribute[] attrs, + final boolean skipDebug) + { + byte[] b = this.b; // the bytecode array + char[] c = new char[maxStringLength]; // buffer used to read strings + int i, j, k; // loop variables + int u, v, w; // indexes in b + Attribute attr; + + int access; + String name; + String desc; + String attrName; + String signature; + int anns = 0; + int ianns = 0; + Attribute cattrs = null; + + // visits the header + u = header; + access = readUnsignedShort(u); + name = readClass(u + 2, c); + v = items[readUnsignedShort(u + 4)]; + String superClassName = v == 0 ? null : readUTF8(v, c); + String[] implementedItfs = new String[readUnsignedShort(u + 6)]; + w = 0; + u += 8; + for (i = 0; i < implementedItfs.length; ++i) { + implementedItfs[i] = readClass(u, c); + u += 2; + } + + // skips fields and methods + v = u; + i = readUnsignedShort(v); + v += 2; + for (; i > 0; --i) { + j = readUnsignedShort(v + 6); + v += 8; + for (; j > 0; --j) { + v += 6 + readInt(v + 2); + } + } + i = readUnsignedShort(v); + v += 2; + for (; i > 0; --i) { + j = readUnsignedShort(v + 6); + v += 8; + for (; j > 0; --j) { + v += 6 + readInt(v + 2); + } + } + // reads the class's attributes + signature = null; + String sourceFile = null; + String sourceDebug = null; + String enclosingOwner = null; + String enclosingName = null; + String enclosingDesc = null; + + i = readUnsignedShort(v); + v += 2; + for (; i > 0; --i) { + attrName = readUTF8(v, c); + if (attrName.equals("SourceFile")) { + sourceFile = readUTF8(v + 6, c); + } else if (attrName.equals("Deprecated")) { + access |= Opcodes.ACC_DEPRECATED; + } else if (attrName.equals("Synthetic")) { + access |= Opcodes.ACC_SYNTHETIC; + } else if (attrName.equals("Annotation")) { + access |= Opcodes.ACC_ANNOTATION; + } else if (attrName.equals("Enum")) { + access |= Opcodes.ACC_ENUM; + } else if (attrName.equals("InnerClasses")) { + w = v + 6; + } else if (attrName.equals("Signature")) { + signature = readUTF8(v + 6, c); + } else if (attrName.equals("SourceDebugExtension")) { + int len = readInt(v + 2); + sourceDebug = readUTF(v + 6, len, new char[len]); + } else if (attrName.equals("EnclosingMethod")) { + enclosingOwner = readClass(v + 6, c); + int item = readUnsignedShort(v + 8); + if (item != 0) { + enclosingName = readUTF8(items[item], c); + enclosingDesc = readUTF8(items[item] + 2, c); + } + } else if (attrName.equals("RuntimeVisibleAnnotations")) { + anns = v + 6; + } else if (attrName.equals("RuntimeInvisibleAnnotations")) { + ianns = v + 6; + } else { + attr = readAttribute(attrs, + attrName, + v + 6, + readInt(v + 2), + c, + -1, + null); + if (attr != null) { + attr.next = cattrs; + cattrs = attr; + } + } + v += 6 + readInt(v + 2); + } + // calls the visit method + classVisitor.visit(readInt(4), + access, + name, + signature, + superClassName, + implementedItfs); + + // calls the visitSource method + if (sourceFile != null || sourceDebug != null) { + classVisitor.visitSource(sourceFile, sourceDebug); + } + + // calls the visitOuterClass method + if (enclosingOwner != null) { + classVisitor.visitOuterClass(enclosingOwner, + enclosingName, + enclosingDesc); + } + + // visits the class annotations + for (i = 1; i >= 0; --i) { + v = i == 0 ? ianns : anns; + if (v != 0) { + j = readUnsignedShort(v); + v += 2; + for (; j > 0; --j) { + desc = readUTF8(v, c); + v += 2; + v = readAnnotationValues(v, + c, + classVisitor.visitAnnotation(desc, i != 0)); + } + } + } + + // visits the class attributes + while (cattrs != null) { + attr = cattrs.next; + cattrs.next = null; + classVisitor.visitAttribute(cattrs); + cattrs = attr; + } + + // class the visitInnerClass method + if (w != 0) { + i = readUnsignedShort(w); + w += 2; + for (; i > 0; --i) { + classVisitor.visitInnerClass(readUnsignedShort(w) == 0 + ? null + : readClass(w, c), readUnsignedShort(w +... [truncated message content] |
From: <ls...@us...> - 2007-01-07 13:57:34
|
Revision: 3035 http://jnode.svn.sourceforge.net/jnode/?rev=3035&view=rev Author: lsantha Date: 2007-01-07 05:57:32 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Added Paths: ----------- trunk/core/src/classpath/org/org/objectweb/asm/xml/ trunk/core/src/classpath/org/org/objectweb/asm/xml/ASMContentHandler.java trunk/core/src/classpath/org/org/objectweb/asm/xml/Processor.java trunk/core/src/classpath/org/org/objectweb/asm/xml/SAXAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/xml/SAXAnnotationAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/xml/SAXClassAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/xml/SAXCodeAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/xml/SAXFieldAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/xml/asm-xml.dtd trunk/core/src/classpath/org/org/objectweb/asm/xml/package.html Added: trunk/core/src/classpath/org/org/objectweb/asm/xml/ASMContentHandler.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/xml/ASMContentHandler.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/xml/ASMContentHandler.java 2007-01-07 13:57:32 UTC (rev 3035) @@ -0,0 +1,1215 @@ +/*** + * ASM XML Adapter + * Copyright (c) 2004, Eugene Kuleshov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.xml; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * A {@link org.xml.sax.ContentHandler ContentHandler} that transforms XML + * document into Java class file. This class can be feeded by any kind of SAX + * 2.0 event producers, e.g. XML parser, XSLT or XPath engines, or custom code. + * + * @see org.objectweb.asm.xml.SAXClassAdapter + * @see org.objectweb.asm.xml.Processor + * + * @author Eugene Kuleshov + */ +public class ASMContentHandler extends DefaultHandler implements Opcodes { + /** + * Stack of the intermediate processing contexts. + */ + private List stack = new ArrayList(); + + /** + * Complete name of the current element. + */ + private String match = ""; + + /** + * <tt>true</tt> if the maximum stack size and number of local variables + * must be automatically computed. + */ + protected boolean computeMax; + + /** + * Output stream to write result bytecode. + */ + protected OutputStream os; + + /** + * Current instance of the {@link ClassWriter ClassWriter} used to write + * class bytecode. + */ + protected ClassWriter cw; + + /** + * Map of the active {@link Label Label} instances for current method. + */ + protected Map labels; + + private static final String BASE = "class"; + + private final RuleSet RULES = new RuleSet(); + { + RULES.add(BASE, new ClassRule()); + RULES.add(BASE + "/interfaces/interface", new InterfaceRule()); + RULES.add(BASE + "/interfaces", new InterfacesRule()); + RULES.add(BASE + "/outerclass", new OuterClassRule()); + RULES.add(BASE + "/innerclass", new InnerClassRule()); + RULES.add(BASE + "/source", new SourceRule()); + RULES.add(BASE + "/field", new FieldRule()); + + RULES.add(BASE + "/method", new MethodRule()); + RULES.add(BASE + "/method/exceptions/exception", new ExceptionRule()); + RULES.add(BASE + "/method/exceptions", new ExceptionsRule()); + + RULES.add(BASE + "/method/annotationDefault", + new AnnotationDefaultRule()); + + RULES.add(BASE + "/method/code/*", new OpcodesRule()); // opcodes + + RULES.add(BASE + "/method/code/TABLESWITCH", new TableSwitchRule()); + RULES.add(BASE + "/method/code/TABLESWITCH/label", + new TableSwitchLabelRule()); + RULES.add(BASE + "/method/code/LOOKUPSWITCH", new LookupSwitchRule()); + RULES.add(BASE + "/method/code/LOOKUPSWITCH/label", + new LookupSwitchLabelRule()); + + RULES.add(BASE + "/method/code/Label", new LabelRule()); + RULES.add(BASE + "/method/code/TryCatch", new TryCatchRule()); + RULES.add(BASE + "/method/code/LineNumber", new LineNumberRule()); + RULES.add(BASE + "/method/code/LocalVar", new LocalVarRule()); + RULES.add(BASE + "/method/code/Max", new MaxRule()); + + RULES.add("*/annotation", new AnnotationRule()); + RULES.add("*/parameterAnnotation", new AnnotationParameterRule()); + RULES.add("*/annotationValue", new AnnotationValueRule()); + RULES.add("*/annotationValueAnnotation", + new AnnotationValueAnnotationRule()); + RULES.add("*/annotationValueEnum", new AnnotationValueEnumRule()); + RULES.add("*/annotationValueArray", new AnnotationValueArrayRule()); + } + + private static interface OpcodeGroup { + public static final int INSN = 0; + public static final int INSN_INT = 1; + public static final int INSN_VAR = 2; + public static final int INSN_TYPE = 3; + public static final int INSN_FIELD = 4; + public static final int INSN_METHOD = 5; + public static final int INSN_JUMP = 6; + public static final int INSN_LDC = 7; + public static final int INSN_IINC = 8; + public static final int INSN_MULTIANEWARRAY = 9; + } + + /** + * Map of the opcode names to opcode and opcode group + */ + static final Map OPCODES = new HashMap(); + static { + OPCODES.put("NOP", new Opcode(NOP, OpcodeGroup.INSN)); + OPCODES.put("ACONST_NULL", new Opcode(ACONST_NULL, OpcodeGroup.INSN)); + OPCODES.put("ICONST_M1", new Opcode(ICONST_M1, OpcodeGroup.INSN)); + OPCODES.put("ICONST_0", new Opcode(ICONST_0, OpcodeGroup.INSN)); + OPCODES.put("ICONST_1", new Opcode(ICONST_1, OpcodeGroup.INSN)); + OPCODES.put("ICONST_2", new Opcode(ICONST_2, OpcodeGroup.INSN)); + OPCODES.put("ICONST_3", new Opcode(ICONST_3, OpcodeGroup.INSN)); + OPCODES.put("ICONST_4", new Opcode(ICONST_4, OpcodeGroup.INSN)); + OPCODES.put("ICONST_5", new Opcode(ICONST_5, OpcodeGroup.INSN)); + OPCODES.put("LCONST_0", new Opcode(LCONST_0, OpcodeGroup.INSN)); + OPCODES.put("LCONST_1", new Opcode(LCONST_1, OpcodeGroup.INSN)); + OPCODES.put("FCONST_0", new Opcode(FCONST_0, OpcodeGroup.INSN)); + OPCODES.put("FCONST_1", new Opcode(FCONST_1, OpcodeGroup.INSN)); + OPCODES.put("FCONST_2", new Opcode(FCONST_2, OpcodeGroup.INSN)); + OPCODES.put("DCONST_0", new Opcode(DCONST_0, OpcodeGroup.INSN)); + OPCODES.put("DCONST_1", new Opcode(DCONST_1, OpcodeGroup.INSN)); + OPCODES.put("BIPUSH", new Opcode(BIPUSH, OpcodeGroup.INSN_INT)); + OPCODES.put("SIPUSH", new Opcode(SIPUSH, OpcodeGroup.INSN_INT)); + OPCODES.put("LDC", new Opcode(LDC, OpcodeGroup.INSN_LDC)); + OPCODES.put("ILOAD", new Opcode(ILOAD, OpcodeGroup.INSN_VAR)); + OPCODES.put("LLOAD", new Opcode(LLOAD, OpcodeGroup.INSN_VAR)); + OPCODES.put("FLOAD", new Opcode(FLOAD, OpcodeGroup.INSN_VAR)); + OPCODES.put("DLOAD", new Opcode(DLOAD, OpcodeGroup.INSN_VAR)); + OPCODES.put("ALOAD", new Opcode(ALOAD, OpcodeGroup.INSN_VAR)); + OPCODES.put("IALOAD", new Opcode(IALOAD, OpcodeGroup.INSN)); + OPCODES.put("LALOAD", new Opcode(LALOAD, OpcodeGroup.INSN)); + OPCODES.put("FALOAD", new Opcode(FALOAD, OpcodeGroup.INSN)); + OPCODES.put("DALOAD", new Opcode(DALOAD, OpcodeGroup.INSN)); + OPCODES.put("AALOAD", new Opcode(AALOAD, OpcodeGroup.INSN)); + OPCODES.put("BALOAD", new Opcode(BALOAD, OpcodeGroup.INSN)); + OPCODES.put("CALOAD", new Opcode(CALOAD, OpcodeGroup.INSN)); + OPCODES.put("SALOAD", new Opcode(SALOAD, OpcodeGroup.INSN)); + OPCODES.put("ISTORE", new Opcode(ISTORE, OpcodeGroup.INSN_VAR)); + OPCODES.put("LSTORE", new Opcode(LSTORE, OpcodeGroup.INSN_VAR)); + OPCODES.put("FSTORE", new Opcode(FSTORE, OpcodeGroup.INSN_VAR)); + OPCODES.put("DSTORE", new Opcode(DSTORE, OpcodeGroup.INSN_VAR)); + OPCODES.put("ASTORE", new Opcode(ASTORE, OpcodeGroup.INSN_VAR)); + OPCODES.put("IASTORE", new Opcode(IASTORE, OpcodeGroup.INSN)); + OPCODES.put("LASTORE", new Opcode(LASTORE, OpcodeGroup.INSN)); + OPCODES.put("FASTORE", new Opcode(FASTORE, OpcodeGroup.INSN)); + OPCODES.put("DASTORE", new Opcode(DASTORE, OpcodeGroup.INSN)); + OPCODES.put("AASTORE", new Opcode(AASTORE, OpcodeGroup.INSN)); + OPCODES.put("BASTORE", new Opcode(BASTORE, OpcodeGroup.INSN)); + OPCODES.put("CASTORE", new Opcode(CASTORE, OpcodeGroup.INSN)); + OPCODES.put("SASTORE", new Opcode(SASTORE, OpcodeGroup.INSN)); + OPCODES.put("POP", new Opcode(POP, OpcodeGroup.INSN)); + OPCODES.put("POP2", new Opcode(POP2, OpcodeGroup.INSN)); + OPCODES.put("DUP", new Opcode(DUP, OpcodeGroup.INSN)); + OPCODES.put("DUP_X1", new Opcode(DUP_X1, OpcodeGroup.INSN)); + OPCODES.put("DUP_X2", new Opcode(DUP_X2, OpcodeGroup.INSN)); + OPCODES.put("DUP2", new Opcode(DUP2, OpcodeGroup.INSN)); + OPCODES.put("DUP2_X1", new Opcode(DUP2_X1, OpcodeGroup.INSN)); + OPCODES.put("DUP2_X2", new Opcode(DUP2_X2, OpcodeGroup.INSN)); + OPCODES.put("SWAP", new Opcode(SWAP, OpcodeGroup.INSN)); + OPCODES.put("IADD", new Opcode(IADD, OpcodeGroup.INSN)); + OPCODES.put("LADD", new Opcode(LADD, OpcodeGroup.INSN)); + OPCODES.put("FADD", new Opcode(FADD, OpcodeGroup.INSN)); + OPCODES.put("DADD", new Opcode(DADD, OpcodeGroup.INSN)); + OPCODES.put("ISUB", new Opcode(ISUB, OpcodeGroup.INSN)); + OPCODES.put("LSUB", new Opcode(LSUB, OpcodeGroup.INSN)); + OPCODES.put("FSUB", new Opcode(FSUB, OpcodeGroup.INSN)); + OPCODES.put("DSUB", new Opcode(DSUB, OpcodeGroup.INSN)); + OPCODES.put("IMUL", new Opcode(IMUL, OpcodeGroup.INSN)); + OPCODES.put("LMUL", new Opcode(LMUL, OpcodeGroup.INSN)); + OPCODES.put("FMUL", new Opcode(FMUL, OpcodeGroup.INSN)); + OPCODES.put("DMUL", new Opcode(DMUL, OpcodeGroup.INSN)); + OPCODES.put("IDIV", new Opcode(IDIV, OpcodeGroup.INSN)); + OPCODES.put("LDIV", new Opcode(LDIV, OpcodeGroup.INSN)); + OPCODES.put("FDIV", new Opcode(FDIV, OpcodeGroup.INSN)); + OPCODES.put("DDIV", new Opcode(DDIV, OpcodeGroup.INSN)); + OPCODES.put("IREM", new Opcode(IREM, OpcodeGroup.INSN)); + OPCODES.put("LREM", new Opcode(LREM, OpcodeGroup.INSN)); + OPCODES.put("FREM", new Opcode(FREM, OpcodeGroup.INSN)); + OPCODES.put("DREM", new Opcode(DREM, OpcodeGroup.INSN)); + OPCODES.put("INEG", new Opcode(INEG, OpcodeGroup.INSN)); + OPCODES.put("LNEG", new Opcode(LNEG, OpcodeGroup.INSN)); + OPCODES.put("FNEG", new Opcode(FNEG, OpcodeGroup.INSN)); + OPCODES.put("DNEG", new Opcode(DNEG, OpcodeGroup.INSN)); + OPCODES.put("ISHL", new Opcode(ISHL, OpcodeGroup.INSN)); + OPCODES.put("LSHL", new Opcode(LSHL, OpcodeGroup.INSN)); + OPCODES.put("ISHR", new Opcode(ISHR, OpcodeGroup.INSN)); + OPCODES.put("LSHR", new Opcode(LSHR, OpcodeGroup.INSN)); + OPCODES.put("IUSHR", new Opcode(IUSHR, OpcodeGroup.INSN)); + OPCODES.put("LUSHR", new Opcode(LUSHR, OpcodeGroup.INSN)); + OPCODES.put("IAND", new Opcode(IAND, OpcodeGroup.INSN)); + OPCODES.put("LAND", new Opcode(LAND, OpcodeGroup.INSN)); + OPCODES.put("IOR", new Opcode(IOR, OpcodeGroup.INSN)); + OPCODES.put("LOR", new Opcode(LOR, OpcodeGroup.INSN)); + OPCODES.put("IXOR", new Opcode(IXOR, OpcodeGroup.INSN)); + OPCODES.put("LXOR", new Opcode(LXOR, OpcodeGroup.INSN)); + OPCODES.put("IINC", new Opcode(IINC, OpcodeGroup.INSN_IINC)); + OPCODES.put("I2L", new Opcode(I2L, OpcodeGroup.INSN)); + OPCODES.put("I2F", new Opcode(I2F, OpcodeGroup.INSN)); + OPCODES.put("I2D", new Opcode(I2D, OpcodeGroup.INSN)); + OPCODES.put("L2I", new Opcode(L2I, OpcodeGroup.INSN)); + OPCODES.put("L2F", new Opcode(L2F, OpcodeGroup.INSN)); + OPCODES.put("L2D", new Opcode(L2D, OpcodeGroup.INSN)); + OPCODES.put("F2I", new Opcode(F2I, OpcodeGroup.INSN)); + OPCODES.put("F2L", new Opcode(F2L, OpcodeGroup.INSN)); + OPCODES.put("F2D", new Opcode(F2D, OpcodeGroup.INSN)); + OPCODES.put("D2I", new Opcode(D2I, OpcodeGroup.INSN)); + OPCODES.put("D2L", new Opcode(D2L, OpcodeGroup.INSN)); + OPCODES.put("D2F", new Opcode(D2F, OpcodeGroup.INSN)); + OPCODES.put("I2B", new Opcode(I2B, OpcodeGroup.INSN)); + OPCODES.put("I2C", new Opcode(I2C, OpcodeGroup.INSN)); + OPCODES.put("I2S", new Opcode(I2S, OpcodeGroup.INSN)); + OPCODES.put("LCMP", new Opcode(LCMP, OpcodeGroup.INSN)); + OPCODES.put("FCMPL", new Opcode(FCMPL, OpcodeGroup.INSN)); + OPCODES.put("FCMPG", new Opcode(FCMPG, OpcodeGroup.INSN)); + OPCODES.put("DCMPL", new Opcode(DCMPL, OpcodeGroup.INSN)); + OPCODES.put("DCMPG", new Opcode(DCMPG, OpcodeGroup.INSN)); + OPCODES.put("IFEQ", new Opcode(IFEQ, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IFNE", new Opcode(IFNE, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IFLT", new Opcode(IFLT, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IFGE", new Opcode(IFGE, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IFGT", new Opcode(IFGT, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IFLE", new Opcode(IFLE, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IF_ICMPEQ", new Opcode(IF_ICMPEQ, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IF_ICMPNE", new Opcode(IF_ICMPNE, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IF_ICMPLT", new Opcode(IF_ICMPLT, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IF_ICMPGE", new Opcode(IF_ICMPGE, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IF_ICMPGT", new Opcode(IF_ICMPGT, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IF_ICMPLE", new Opcode(IF_ICMPLE, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IF_ACMPEQ", new Opcode(IF_ACMPEQ, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IF_ACMPNE", new Opcode(IF_ACMPNE, OpcodeGroup.INSN_JUMP)); + OPCODES.put("GOTO", new Opcode(GOTO, OpcodeGroup.INSN_JUMP)); + OPCODES.put("JSR", new Opcode(JSR, OpcodeGroup.INSN_JUMP)); + OPCODES.put("RET", new Opcode(RET, OpcodeGroup.INSN_VAR)); + // OPCODES.put( "TABLESWITCH", new Opcode( TABLESWITCH, + // "visiTableSwitchInsn")); + // OPCODES.put( "LOOKUPSWITCH", new Opcode( LOOKUPSWITCH, + // "visitLookupSwitch")); + OPCODES.put("IRETURN", new Opcode(IRETURN, OpcodeGroup.INSN)); + OPCODES.put("LRETURN", new Opcode(LRETURN, OpcodeGroup.INSN)); + OPCODES.put("FRETURN", new Opcode(FRETURN, OpcodeGroup.INSN)); + OPCODES.put("DRETURN", new Opcode(DRETURN, OpcodeGroup.INSN)); + OPCODES.put("ARETURN", new Opcode(ARETURN, OpcodeGroup.INSN)); + OPCODES.put("RETURN", new Opcode(RETURN, OpcodeGroup.INSN)); + OPCODES.put("GETSTATIC", new Opcode(GETSTATIC, OpcodeGroup.INSN_FIELD)); + OPCODES.put("PUTSTATIC", new Opcode(PUTSTATIC, OpcodeGroup.INSN_FIELD)); + OPCODES.put("GETFIELD", new Opcode(GETFIELD, OpcodeGroup.INSN_FIELD)); + OPCODES.put("PUTFIELD", new Opcode(PUTFIELD, OpcodeGroup.INSN_FIELD)); + OPCODES.put("INVOKEVIRTUAL", new Opcode(INVOKEVIRTUAL, + OpcodeGroup.INSN_METHOD)); + OPCODES.put("INVOKESPECIAL", new Opcode(INVOKESPECIAL, + OpcodeGroup.INSN_METHOD)); + OPCODES.put("INVOKESTATIC", new Opcode(INVOKESTATIC, + OpcodeGroup.INSN_METHOD)); + OPCODES.put("INVOKEINTERFACE", new Opcode(INVOKEINTERFACE, + OpcodeGroup.INSN_METHOD)); + OPCODES.put("NEW", new Opcode(NEW, OpcodeGroup.INSN_TYPE)); + OPCODES.put("NEWARRAY", new Opcode(NEWARRAY, OpcodeGroup.INSN_INT)); + OPCODES.put("ANEWARRAY", new Opcode(ANEWARRAY, OpcodeGroup.INSN_TYPE)); + OPCODES.put("ARRAYLENGTH", new Opcode(ARRAYLENGTH, OpcodeGroup.INSN)); + OPCODES.put("ATHROW", new Opcode(ATHROW, OpcodeGroup.INSN)); + OPCODES.put("CHECKCAST", new Opcode(CHECKCAST, OpcodeGroup.INSN_TYPE)); + OPCODES.put("INSTANCEOF", new Opcode(INSTANCEOF, OpcodeGroup.INSN_TYPE)); + OPCODES.put("MONITORENTER", new Opcode(MONITORENTER, OpcodeGroup.INSN)); + OPCODES.put("MONITOREXIT", new Opcode(MONITOREXIT, OpcodeGroup.INSN)); + OPCODES.put("MULTIANEWARRAY", new Opcode(MULTIANEWARRAY, + OpcodeGroup.INSN_MULTIANEWARRAY)); + OPCODES.put("IFNULL", new Opcode(IFNULL, OpcodeGroup.INSN_JUMP)); + OPCODES.put("IFNONNULL", new Opcode(IFNONNULL, OpcodeGroup.INSN_JUMP)); + } + + /** + * Constructs a new {@link ASMContentHandler ASMContentHandler} object. + * + * @param os output stream to write generated class. + * @param computeMax <tt>true</tt> if the maximum stack size and the + * maximum number of local variables must be automatically computed. + * This value is passed to {@link ClassWriter ClassWriter} instance. + */ + public ASMContentHandler(OutputStream os, boolean computeMax) { + this.os = os; + this.computeMax = computeMax; + } + + /** + * Returns the bytecode of the class that was build with underneath class + * writer. + * + * @return the bytecode of the class that was build with underneath class + * writer or null if there are no classwriter created. + */ + public byte[] toByteArray() { + return cw == null ? null : cw.toByteArray(); + } + + /** + * Process notification of the start of an XML element being reached. + * + * @param ns - The Namespace URI, or the empty string if the element has no + * Namespace URI or if Namespace processing is not being performed. + * @param localName - The local name (without prefix), or the empty string + * if Namespace processing is not being performed. + * @param qName - The qualified name (with prefix), or the empty string if + * qualified names are not available. + * @param list - The attributes attached to the element. If there are no + * attributes, it shall be an empty Attributes object. + * @exception SAXException if a parsing error is to be reported + */ + public final void startElement( + String ns, + String localName, + String qName, + Attributes list) throws SAXException + { + // the actual element name is either in localName or qName, depending + // on whether the parser is namespace aware + String name = localName; + if (name == null || name.length() < 1) { + name = qName; + } + + // Compute the current matching rule + StringBuffer sb = new StringBuffer(match); + if (match.length() > 0) { + sb.append('/'); + } + sb.append(name); + match = sb.toString(); + + // Fire "begin" events for all relevant rules + Rule r = (Rule) RULES.match(match); + if (r != null) + r.begin(name, list); + } + + /** + * Process notification of the end of an XML element being reached. + * + * @param ns - The Namespace URI, or the empty string if the element has no + * Namespace URI or if Namespace processing is not being performed. + * @param localName - The local name (without prefix), or the empty string + * if Namespace processing is not being performed. + * @param qName - The qualified XML 1.0 name (with prefix), or the empty + * string if qualified names are not available. + * + * @exception SAXException if a parsing error is to be reported + */ + public final void endElement(String ns, String localName, String qName) + throws SAXException + { + // the actual element name is either in localName or qName, depending + // on whether the parser is namespace aware + String name = localName; + if (name == null || name.length() < 1) { + name = qName; + } + + // Fire "end" events for all relevant rules in reverse order + Rule r = (Rule) RULES.match(match); + if (r != null) + r.end(name); + + // Recover the previous match expression + int slash = match.lastIndexOf('/'); + if (slash >= 0) { + match = match.substring(0, slash); + } else { + match = ""; + } + } + + /** + * Process notification of the end of a document and write generated + * bytecode into output stream. + * + * @exception SAXException if parsing or writing error is to be reported. + */ + public final void endDocument() throws SAXException { + try { + os.write(cw.toByteArray()); + } catch (IOException ex) { + throw new SAXException(ex.toString(), ex); + } + } + + /** + * Return the top object on the stack without removing it. If there are no + * objects on the stack, return <code>null</code>. + * + * @return the top object on the stack without removing it. + */ + final Object peek() { + return stack.size() == 0 ? null : stack.get(stack.size() - 1); + } + + /** + * Return the n'th object down the stack, where 0 is the top element and + * [getCount()-1] is the bottom element. If the specified index is out of + * range, return <code>null</code>. + * + * @param n Index of the desired element, where 0 is the top of the stack, 1 + * is the next element down, and so on. + * @return the n'th object down the stack. + */ + final Object peek(int n) { + return stack.size() < (n + 1) ? null : stack.get(n); + } + + /** + * Pop the top object off of the stack, and return it. If there are no + * objects on the stack, return <code>null</code>. + * + * @return the top object off of the stack. + */ + final Object pop() { + return stack.size() == 0 ? null : stack.remove(stack.size() - 1); + } + + /** + * Push a new object onto the top of the object stack. + * + * @param object The new object + */ + final void push(Object object) { + stack.add(object); + } + + private static final class RuleSet { + private Map rules = new HashMap(); + + private List lpatterns = new ArrayList(); + + private List rpatterns = new ArrayList(); + + public void add(String path, Object rule) { + String pattern = path; + if (path.startsWith("*/")) { + pattern = path.substring(1); + lpatterns.add(pattern); + } else if (path.endsWith("/*")) { + pattern = path.substring(0, path.length() - 1); + rpatterns.add(pattern); + } + rules.put(pattern, rule); + } + + public Object match(String path) { + if (rules.containsKey(path)) { + return rules.get(path); + } + + int n = path.lastIndexOf('/'); + for (Iterator it = lpatterns.iterator(); it.hasNext();) { + String pattern = (String) it.next(); + if (path.substring(n).endsWith(pattern)) { + return rules.get(pattern); + } + } + + for (Iterator it = rpatterns.iterator(); it.hasNext();) { + String pattern = (String) it.next(); + if (path.startsWith(pattern)) { + return rules.get(pattern); + } + } + + return null; + } + + } + + /** + * Rule + */ + protected abstract class Rule { + + public void begin(String name, Attributes attrs) { + } + + public void end(String name) { + } + + protected final Object getValue(String desc, String val) { + Object value = null; + if (val != null) { + if (desc.equals("Ljava/lang/String;")) { + value = decode(val); + } else if ("Ljava/lang/Integer;".equals(desc) + || "I".equals(desc) || "S".equals(desc) + || "B".equals(desc) || "C".equals(desc) + || desc.equals("Z")) + { + value = new Integer(val); + + } else if ("Ljava/lang/Short;".equals(desc)) { + value = new Short(val); + + } else if ("Ljava/lang/Byte;".equals(desc)) { + value = new Byte(val); + + } else if ("Ljava/lang/Character;".equals(desc)) { + value = new Character(decode(val).charAt(0)); + + } else if ("Ljava/lang/Boolean;".equals(desc)) { + value = Boolean.valueOf(val); + + // } else if ("Ljava/lang/Integer;".equals(desc) + // || desc.equals("I")) + // { + // value = new Integer(val); + // } else if ("Ljava/lang/Character;".equals(desc) + // || desc.equals("C")) + // { + // value = new Character(decode(val).charAt(0)); + // } else if ("Ljava/lang/Short;".equals(desc) || + // desc.equals("S")) + // { + // value = Short.valueOf(val); + // } else if ("Ljava/lang/Byte;".equals(desc) || + // desc.equals("B")) + // { + // value = Byte.valueOf(val); + + } else if ("Ljava/lang/Long;".equals(desc) || desc.equals("J")) + { + value = new Long(val); + } else if ("Ljava/lang/Float;".equals(desc) || desc.equals("F")) + { + value = new Float(val); + } else if ("Ljava/lang/Double;".equals(desc) + || desc.equals("D")) + { + value = new Double(val); + } else if (Type.getDescriptor(Type.class).equals(desc)) { + value = Type.getType(val); + + // } else if ("[I".equals(desc)) { + // value = new int[0]; // TODO + // } else if ("[C".equals(desc)) { + // value = new char[0]; // TODO + // } else if ("[Z".equals(desc)) { + // value = new boolean[0]; // TODO + // } else if ("[S".equals(desc)) { + // value = new short[0]; // TODO + // } else if ("[B".equals(desc)) { + // value = new byte[0]; // TODO + // } else if ("[J".equals(desc)) { + // value = new long[0]; // TODO + // } else if ("[F".equals(desc)) { + // value = new float[0]; // TODO + // } else if ("[D".equals(desc)) { + // value = new double[0]; // TODO + + } else { + throw new RuntimeException("Invalid value:" + val + + " desc:" + desc + " ctx:" + this); + } + } + return value; + } + + private final String decode(String val) { + StringBuffer sb = new StringBuffer(val.length()); + try { + int n = 0; + while (n < val.length()) { + char c = val.charAt(n); + if (c == '\\') { + n++; + c = val.charAt(n); + if (c == '\\') { + sb.append('\\'); + } else { + n++; // skip 'u' + sb.append((char) Integer.parseInt(val.substring(n, + n + 4), 16)); + n += 3; + } + } else { + sb.append(c); + } + n++; + } + + } catch (RuntimeException ex) { + System.err.println(val + "\n" + ex.toString()); + ex.printStackTrace(); + throw ex; + } + return sb.toString(); + } + + protected final Label getLabel(Object label) { + Label lbl = (Label) labels.get(label); + if (lbl == null) { + lbl = new Label(); + labels.put(label, lbl); + } + return lbl; + } + + // TODO verify move to stack + protected final MethodVisitor getCodeVisitor() { + return (MethodVisitor) peek(); + } + + protected final int getAccess(String s) { + int access = 0; + if (s.indexOf("public") != -1) + access |= Opcodes.ACC_PUBLIC; + if (s.indexOf("private") != -1) + access |= Opcodes.ACC_PRIVATE; + if (s.indexOf("protected") != -1) + access |= Opcodes.ACC_PROTECTED; + if (s.indexOf("static") != -1) + access |= Opcodes.ACC_STATIC; + if (s.indexOf("final") != -1) + access |= Opcodes.ACC_FINAL; + if (s.indexOf("super") != -1) + access |= Opcodes.ACC_SUPER; + if (s.indexOf("synchronized") != -1) + access |= Opcodes.ACC_SYNCHRONIZED; + if (s.indexOf("volatile") != -1) + access |= Opcodes.ACC_VOLATILE; + if (s.indexOf("bridge") != -1) + access |= Opcodes.ACC_BRIDGE; + if (s.indexOf("varargs") != -1) + access |= Opcodes.ACC_VARARGS; + if (s.indexOf("transient") != -1) + access |= Opcodes.ACC_TRANSIENT; + if (s.indexOf("native") != -1) + access |= Opcodes.ACC_NATIVE; + if (s.indexOf("interface") != -1) + access |= Opcodes.ACC_INTERFACE; + if (s.indexOf("abstract") != -1) + access |= Opcodes.ACC_ABSTRACT; + if (s.indexOf("strict") != -1) + access |= Opcodes.ACC_STRICT; + if (s.indexOf("synthetic") != -1) + access |= Opcodes.ACC_SYNTHETIC; + if (s.indexOf("annotation") != -1) + access |= Opcodes.ACC_ANNOTATION; + if (s.indexOf("enum") != -1) + access |= Opcodes.ACC_ENUM; + if (s.indexOf("deprecated") != -1) + access |= Opcodes.ACC_DEPRECATED; + return access; + } + + } + + /** + * ClassRule + */ + private final class ClassRule extends Rule { + + public final void begin(String name, Attributes attrs) { + int major = Integer.parseInt(attrs.getValue("major")); + int minor = Integer.parseInt(attrs.getValue("minor")); + cw = new ClassWriter(computeMax); + Map vals = new HashMap(); + vals.put("version", new Integer(minor << 16 | major)); + vals.put("access", attrs.getValue("access")); + vals.put("name", attrs.getValue("name")); + vals.put("parent", attrs.getValue("parent")); + vals.put("source", attrs.getValue("source")); + vals.put("signature", attrs.getValue("signature")); + vals.put("interfaces", new ArrayList()); + push(vals); + // values will be extracted in InterfacesRule.end(); + } + + } + + private final class SourceRule extends Rule { + + public void begin(String name, Attributes attrs) { + String file = attrs.getValue("file"); + String debug = attrs.getValue("debug"); + cw.visitSource(file, debug); + } + + } + + /** + * InterfaceRule + */ + private final class InterfaceRule extends Rule { + + public final void begin(String name, Attributes attrs) { + ((List) ((Map) peek()).get("interfaces")).add(attrs.getValue("name")); + } + + } + + /** + * InterfacesRule + */ + private final class InterfacesRule extends Rule { + + public final void end(String element) { + Map vals = (Map) pop(); + int version = ((Integer) vals.get("version")).intValue(); + int access = getAccess((String) vals.get("access")); + String name = (String) vals.get("name"); + String signature = (String) vals.get("signature"); + String parent = (String) vals.get("parent"); + List infs = (List) vals.get("interfaces"); + String[] interfaces = (String[]) infs.toArray(new String[infs.size()]); + cw.visit(version, access, name, signature, parent, interfaces); + push(cw); + } + + } + + /** + * OuterClassRule + */ + private final class OuterClassRule extends Rule { + + public final void begin(String element, Attributes attrs) { + String owner = attrs.getValue("owner"); + String name = attrs.getValue("name"); + String desc = attrs.getValue("desc"); + cw.visitOuterClass(owner, name, desc); + } + + } + + /** + * InnerClassRule + */ + private final class InnerClassRule extends Rule { + + public final void begin(String element, Attributes attrs) { + int access = getAccess(attrs.getValue("access")); + String name = attrs.getValue("name"); + String outerName = attrs.getValue("outerName"); + String innerName = attrs.getValue("innerName"); + cw.visitInnerClass(name, outerName, innerName, access); + } + + } + + /** + * FieldRule + */ + private final class FieldRule extends Rule { + + public final void begin(String element, Attributes attrs) { + int access = getAccess(attrs.getValue("access")); + String name = attrs.getValue("name"); + String signature = attrs.getValue("signature"); + String desc = attrs.getValue("desc"); + Object value = getValue(desc, attrs.getValue("value")); + push(cw.visitField(access, name, desc, signature, value)); + } + + public void end(String name) { + ((FieldVisitor) pop()).visitEnd(); + } + + } + + /** + * MethodRule + */ + private final class MethodRule extends Rule { + + public final void begin(String name, Attributes attrs) { + labels = new HashMap(); + Map vals = new HashMap(); + vals.put("access", attrs.getValue("access")); + vals.put("name", attrs.getValue("name")); + vals.put("desc", attrs.getValue("desc")); + vals.put("signature", attrs.getValue("signature")); + vals.put("exceptions", new ArrayList()); + push(vals); + // values will be extracted in ExceptionsRule.end(); + } + + public final void end(String name) { + ((MethodVisitor) pop()).visitEnd(); + labels = null; + } + + } + + /** + * ExceptionRule + */ + private final class ExceptionRule extends Rule { + + public final void begin(String name, Attributes attrs) { + ((List) ((Map) peek()).get("exceptions")).add(attrs.getValue("name")); + } + + } + + /** + * ExceptionsRule + */ + private final class ExceptionsRule extends Rule { + + public final void end(String element) { + Map vals = (Map) pop(); + int access = getAccess((String) vals.get("access")); + String name = (String) vals.get("name"); + String desc = (String) vals.get("desc"); + String signature = (String) vals.get("signature"); + List excs = (List) vals.get("exceptions"); + String[] exceptions = (String[]) excs.toArray(new String[excs.size()]); + + push(cw.visitMethod(access, name, desc, signature, exceptions)); + } + + } + + /** + * TableSwitchRule + */ + private class TableSwitchRule extends Rule { + + public final void begin(String name, Attributes attrs) { + Map vals = new HashMap(); + vals.put("min", attrs.getValue("min")); + vals.put("max", attrs.getValue("max")); + vals.put("dflt", attrs.getValue("dflt")); + vals.put("labels", new ArrayList()); + push(vals); + } + + public final void end(String name) { + Map vals = (Map) pop(); + int min = Integer.parseInt((String) vals.get("min")); + int max = Integer.parseInt((String) vals.get("max")); + Label dflt = getLabel(vals.get("dflt")); + List lbls = (List) vals.get("labels"); + Label[] labels = (Label[]) lbls.toArray(new Label[lbls.size()]); + getCodeVisitor().visitTableSwitchInsn(min, max, dflt, labels); + } + + } + + /** + * TableSwitchLabelRule + */ + private final class TableSwitchLabelRule extends Rule { + + public final void begin(String name, Attributes attrs) { + ((List) ((Map) peek()).get("labels")).add(getLabel(attrs.getValue("name"))); + } + + } + + /** + * LookupSwitchRule + */ + private final class LookupSwitchRule extends Rule { + + public final void begin(String name, Attributes attrs) { + Map vals = new HashMap(); + vals.put("dflt", attrs.getValue("dflt")); + vals.put("labels", new ArrayList()); + vals.put("keys", new ArrayList()); + push(vals); + } + + public final void end(String name) { + Map vals = (Map) pop(); + Label dflt = getLabel(vals.get("dflt")); + List keyList = (List) vals.get("keys"); + List lbls = (List) vals.get("labels"); + Label[] labels = (Label[]) lbls.toArray(new Label[lbls.size()]); + int[] keys = new int[keyList.size()]; + for (int i = 0; i < keys.length; i++) { + keys[i] = Integer.parseInt((String) keyList.get(i)); + } + getCodeVisitor().visitLookupSwitchInsn(dflt, keys, labels); + } + + } + + /** + * LookupSwitchLabelRule + */ + private final class LookupSwitchLabelRule extends Rule { + + public final void begin(String name, Attributes attrs) { + Map vals = (Map) peek(); + ((List) vals.get("labels")).add(getLabel(attrs.getValue("name"))); + ((List) vals.get("keys")).add(attrs.getValue("key")); + } + + } + + /** + * LabelRule + */ + private final class LabelRule extends Rule { + + public final void begin(String name, Attributes attrs) { + getCodeVisitor().visitLabel(getLabel(attrs.getValue("name"))); + } + + } + + /** + * TryCatchRule + */ + private final class TryCatchRule extends Rule { + + public final void begin(String name, Attributes attrs) { + Label start = getLabel(attrs.getValue("start")); + Label end = getLabel(attrs.getValue("end")); + Label handler = getLabel(attrs.getValue("handler")); + String type = attrs.getValue("type"); + getCodeVisitor().visitTryCatchBlock(start, end, handler, type); + } + + } + + /** + * LineNumberRule + */ + private final class LineNumberRule extends Rule { + + public final void begin(String name, Attributes attrs) { + int line = Integer.parseInt(attrs.getValue("line")); + Label start = getLabel(attrs.getValue("start")); + getCodeVisitor().visitLineNumber(line, start); + } + + } + + /** + * LocalVarRule + */ + private final class LocalVarRule extends Rule { + + public final void begin(String element, Attributes attrs) { + String name = attrs.getValue("name"); + String desc = attrs.getValue("desc"); + String signature = attrs.getValue("signature"); + Label start = getLabel(attrs.getValue("start")); + Label end = getLabel(attrs.getValue("end")); + int var = Integer.parseInt(attrs.getValue("var")); + getCodeVisitor().visitLocalVariable(name, + desc, + signature, + start, + end, + var); + } + + } + + /** + * OpcodesRule + */ + private final class OpcodesRule extends Rule { + + // public boolean match( String match, String element) { + // return match.startsWith( path) && OPCODES.containsKey( element); + // } + + public final void begin(String element, Attributes attrs) { + Opcode o = ((Opcode) OPCODES.get(element)); + if (o == null) + return; + + switch (o.type) { + case OpcodeGroup.INSN: + getCodeVisitor().visitInsn(o.opcode); + break; + + case OpcodeGroup.INSN_FIELD: + getCodeVisitor().visitFieldInsn(o.opcode, + attrs.getValue("owner"), + attrs.getValue("name"), + attrs.getValue("desc")); + break; + + case OpcodeGroup.INSN_INT: + getCodeVisitor().visitIntInsn(o.opcode, + Integer.parseInt(attrs.getValue("value"))); + break; + + case OpcodeGroup.INSN_JUMP: + getCodeVisitor().visitJumpInsn(o.opcode, + getLabel(attrs.getValue("label"))); + break; + + case OpcodeGroup.INSN_METHOD: + getCodeVisitor().visitMethodInsn(o.opcode, + attrs.getValue("owner"), + attrs.getValue("name"), + attrs.getValue("desc")); + break; + + case OpcodeGroup.INSN_TYPE: + getCodeVisitor().visitTypeInsn(o.opcode, + attrs.getValue("desc")); + break; + + case OpcodeGroup.INSN_VAR: + getCodeVisitor().visitVarInsn(o.opcode, + Integer.parseInt(attrs.getValue("var"))); + break; + + case OpcodeGroup.INSN_IINC: + getCodeVisitor().visitIincInsn(Integer.parseInt(attrs.getValue("var")), + Integer.parseInt(attrs.getValue("inc"))); + break; + + case OpcodeGroup.INSN_LDC: + getCodeVisitor().visitLdcInsn(getValue(attrs.getValue("desc"), + attrs.getValue("cst"))); + break; + + case OpcodeGroup.INSN_MULTIANEWARRAY: + getCodeVisitor().visitMultiANewArrayInsn(attrs.getValue("desc"), + Integer.parseInt(attrs.getValue("dims"))); + break; + + default: + throw new RuntimeException("Invalid element: " + element + + " at " + match); + + } + } + } + + /** + * MaxRule + */ + private final class MaxRule extends Rule { + + public final void begin(String element, Attributes attrs) { + int maxStack = Integer.parseInt(attrs.getValue("maxStack")); + int maxLocals = Integer.parseInt(attrs.getValue("maxLocals")); + getCodeVisitor().visitMaxs(maxStack, maxLocals); + } + + } + + private final class AnnotationRule extends Rule { + + public void begin(String name, Attributes attrs) { + String desc = attrs.getValue("desc"); + boolean visible = Boolean.valueOf(attrs.getValue("visible")) + .booleanValue(); + + Object v = peek(); + if (v instanceof ClassVisitor) { + push(((ClassVisitor) v).visitAnnotation(desc, visible)); + } else if (v instanceof FieldVisitor) { + push(((FieldVisitor) v).visitAnnotation(desc, visible)); + } else if (v instanceof MethodVisitor) { + push(((MethodVisitor) v).visitAnnotation(desc, visible)); + } + } + + public void end(String name) { + ((AnnotationVisitor) pop()).visitEnd(); + } + + } + + private final class AnnotationParameterRule extends Rule { + + public void begin(String name, Attributes attrs) { + int parameter = Integer.parseInt(attrs.getValue("parameter")); + String desc = attrs.getValue("desc"); + boolean visible = Boolean.valueOf(attrs.getValue("visible")) + .booleanValue(); + + push(((MethodVisitor) peek()).visitParameterAnnotation(parameter, + desc, + visible)); + } + + public void end(String name) { + ((AnnotationVisitor) pop()).visitEnd(); + } + + } + + private final class AnnotationValueRule extends Rule { + + public void begin(String nm, Attributes attrs) { + String name = attrs.getValue("name"); + String desc = attrs.getValue("desc"); + String value = attrs.getValue("value"); + ((AnnotationVisitor) peek()).visit(name, getValue(desc, value)); + } + + } + + private final class AnnotationValueEnumRule extends Rule { + + public void begin(String nm, Attributes attrs) { + String name = attrs.getValue("name"); + String desc = attrs.getValue("desc"); + String value = attrs.getValue("value"); + ((AnnotationVisitor) peek()).visitEnum(name, desc, value); + } + + } + + private final class AnnotationValueAnnotationRule extends Rule { + + public void begin(String nm, Attributes attrs) { + String name = attrs.getValue("name"); + String desc = attrs.getValue("desc"); + push(((AnnotationVisitor) peek()).visitAnnotation(name, desc)); + } + + public void end(String name) { + ((AnnotationVisitor) pop()).visitEnd(); + } + + } + + private final class AnnotationValueArrayRule extends Rule { + + public void begin(String nm, Attributes attrs) { + String name = attrs.getValue("name"); + push(((AnnotationVisitor) peek()).visitArray(name)); + } + + public void end(String name) { + ((AnnotationVisitor) pop()).visitEnd(); + } + + } + + private final class AnnotationDefaultRule extends Rule { + + public void begin(String nm, Attributes attrs) { + push(((MethodVisitor) peek()).visitAnnotationDefault()); + } + + public void end(String name) { + ((AnnotationVisitor) pop()).visitEnd(); + } + + } + + /** + * Opcode + */ + private final static class Opcode { + public int opcode; + + public int type; + + public Opcode(int opcode, int type) { + this.opcode = opcode; + this.type = type; + } + + } + +} Added: trunk/core/src/classpath/org/org/objectweb/asm/xml/Processor.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/xml/Processor.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/xml/Processor.java 2007-01-07 13:57:32 UTC (rev 3035) @@ -0,0 +1,1048 @@ +/*** + * ASM XML Adapter + * Copyright (c) 2004, Eugene Kuleshov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.xml; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +import javax.xml.transform.Source; +import javax.xml.transform.Templates; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamSource; + +import org.objectweb.asm.ClassReader; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.ext.LexicalHandler; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.helpers.DefaultHandler; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * Processor is a command line tool that can be used for bytecode waving + * directed by XSL transformation. <p> In order to use a concrete XSLT engine, + * system property <tt>javax.xml.transform.TransformerFactory</tt> must be set + * to one of the following values. + * + * <blockquote> <table border="1" cellspacing="0" cellpadding="3"> <tr> <td>jd.xslt</td> + * <td>jd.xml.xslt.trax.TransformerFactoryImpl</td> </tr> + * + * <tr> <td>Saxon</td> <td>net.sf.saxon.TransformerFactoryImpl</td> </tr> + * + * <tr> <td>Caucho</td> <td>com.caucho.xsl.Xsl</td> </tr> + * + * <tr> <td>Xalan interpeter</td> <td>org.apache.xalan.processor.TransformerFactory</td> + * </tr> + * + * <tr> <td>Xalan xsltc</td> <td>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</td> + * </tr> </table> </blockquote> + * + * @author Eugene Kuleshov + */ +public class Processor { + + public static final int BYTECODE = 1; + + public static final int MULTI_XML = 2; + + public static final int SINGLE_XML = 3; + + private static final String SINGLE_XML_NAME = "classes.xml"; + + private int inRepresentation; + + private int outRepresentation; + + private InputStream input = null; + + private OutputStream output = null; + + private Source xslt = null; + + private boolean computeMax; + + private int n = 0; + + public Processor( + int inRepresenation, + int outRepresentation, + InputStream input, + OutputStream output, + Source xslt) + { + this.inRepresentation = inRepresenation; + this.outRepresentation = outRepresentation; + this.input = input; + this.output = output; + this.xslt = xslt; + this.computeMax = true; + } + + public int process() throws TransformerException, IOException, SAXException + { + ZipInputStream zis = new ZipInputStream(input); + final ZipOutputStream zos = new ZipOutputStream(output); + final OutputStreamWriter osw = new OutputStreamWriter(zos); + + Thread.currentThread() + .setContextClassLoader(getClass().getClassLoader()); + + TransformerFactory tf = TransformerFactory.newInstance(); + if (!tf.getFeature(SAXSource.FEATURE) + || !tf.getFeature(SAXResult.FEATURE)) + return 0; + + SAXTransformerFactory saxtf = (SAXTransformerFactory) tf; + Templates templates = null; + if (xslt != null) { + templates = saxtf.newTemplates(xslt); + } + + // configuring outHandlerFactory + // /////////////////////////////////////////////////////// + + EntryElement entryElement = getEntryElement(zos); + + ContentHandler outDocHandler = null; + switch (outRepresentation) { + case BYTECODE: + outDocHandler = new OutputSlicingHandler(new ASMContentHandlerFactory(zos, + computeMax), + entryElement, + false); + break; + + case MULTI_XML: + outDocHandler = new OutputSlicingHandler(new SAXWriterFactory(osw, + true), + entryElement, + true); + break; + + case SINGLE_XML: + ZipEntry outputEntry = new ZipEntry(SINGLE_XML_NAME); + zos.putNextEntry(outputEntry); + outDocHandler = new SAXWriter(osw, false); + break; + + } + + // configuring inputDocHandlerFactory + // ///////////////////////////////////////////////// + ContentHandler inDocHandler = null; + if (templates == null) { + inDocHandler = outDocHandler; + } else { + inDocHandler = new InputSlicingHandler("class", + outDocHandler, + new TransformerHandlerFactory(saxtf, + templates, + outDocHandler)); + } + ContentHandlerFactory inDocHandlerFactory = new SubdocumentHandlerFactory(inDocHandler); + + if (inDocHandler != null && inRepresentation != SINGLE_XML) { + inDocHandler.startDocument(); + inDocHandler.startElement("", + "classes", + "classes", + new AttributesImpl()); + } + + int i = 0; + ZipEntry ze = null; + while ((ze = zis.getNextEntry()) != null) { + update(ze.getName(), n++); + if (isClassEntry(ze)) { + processEntry(zis, ze, inDocHandlerFactory); + } else { + OutputStream os = entryElement.openEntry(getName(ze)); + copyEntry(zis, os); + entryElement.closeEntry(); + } + + i++; + } + + if (inDocHandler != null && inRepresentation != SINGLE_XML) { + inDocHandler.endElement("", "classes", "classes"); + inDocHandler.endDocument(); + } + + if (outRepresentation == SINGLE_XML) { + zos.closeEntry(); + } + zos.flush(); + zos.close(); + + return i; + } + + private void copyEntry(InputStream is, OutputStream os) throws IOException { + if (outRepresentation == SINGLE_XML) + return; + + byte[] buff = new byte[2048]; + int i; + while ((i = is.read(buff)) != -1) { + os.write(buff, 0, i); + } + } + + private boolean isClassEntry(ZipEntry ze) { + String name = ze.getName(); + return inRepresentation == SINGLE_XML && name.equals(SINGLE_XML_NAME) + || name.endsWith(".class") || name.endsWith(".class.xml"); + } + + private void processEntry( + final ZipInputStream zis, + ZipEntry ze, + ContentHandlerFactory handlerFactory) + { + ContentHandler handler = handlerFactory.createContentHandler(); + try { + + // if (CODE2ASM.equals(command)) { // read bytecode and process it + // // with TraceClassVisitor + // ClassReader cr = new ClassReader(readEntry(zis, ze)); + // cr.accept(new TraceClassVisitor(null, new PrintWriter(os)), + // false); + // } + + boolean singleInputDocument = inRepresentation == SINGLE_XML; + if (inRepresentation == BYTECODE) { // read bytecode and process it + // with handler + ClassReader cr = new ClassReader(readEntry(zis, ze)); + cr.accept(new SAXClassAdapter(handler, singleInputDocument), + false); + + } else { // read XML and process it with handler + XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setContentHandler(handler); + reader.parse(new InputSource(singleInputDocument + ? (InputStream) new ProtectedInputStream(zis) + : new ByteArrayInputStream(readEntry(zis, ze)))); + + } + } catch (Exception ex) { + update(ze.getName(), 0); + update(ex, 0); + } + } + + private EntryElement getEntryElement(ZipOutputStream zos) { + if (outRepresentation == SINGLE_XML) { + return new SingleDocElement(zos); + } + return new ZipEntryElement(zos); + } + + // private ... [truncated message content] |
From: <ls...@us...> - 2007-01-07 13:55:16
|
Revision: 3034 http://jnode.svn.sourceforge.net/jnode/?rev=3034&view=rev Author: lsantha Date: 2007-01-07 05:55:15 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Added Paths: ----------- trunk/core/src/classpath/org/org/objectweb/asm/util/ trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierAbstractVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierAnnotationVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierClassVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierFieldVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierMethodVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/AbstractVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/CheckAnnotationAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/util/CheckClassAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/util/CheckFieldAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/util/CheckMethodAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/util/TraceAbstractVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/TraceAnnotationVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/TraceClassVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/TraceFieldVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/TraceMethodVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/TraceSignatureVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/util/attrs/ trunk/core/src/classpath/org/org/objectweb/asm/util/attrs/ASMStackMapAttribute.java trunk/core/src/classpath/org/org/objectweb/asm/util/attrs/ASMStackMapTableAttribute.java trunk/core/src/classpath/org/org/objectweb/asm/util/attrs/ASMifiable.java trunk/core/src/classpath/org/org/objectweb/asm/util/attrs/Traceable.java trunk/core/src/classpath/org/org/objectweb/asm/util/attrs/package.html trunk/core/src/classpath/org/org/objectweb/asm/util/package.html Added: trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierAbstractVisitor.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierAbstractVisitor.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierAbstractVisitor.java 2007-01-07 13:55:15 UTC (rev 3034) @@ -0,0 +1,226 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.util; + +import java.util.HashMap; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Type; +import org.objectweb.asm.util.attrs.ASMifiable; + +/** + * An abstract ASMifier visitor. + * + * @author Eric Bruneton + */ +public class ASMifierAbstractVisitor extends AbstractVisitor { + + /** + * The name of the variable for this visitor in the produced code. + */ + protected String name; + + /** + * The label names. This map associates String values to Label keys. It is + * used only in ASMifierMethodVisitor. + */ + HashMap labelNames; + + /** + * Constructs a new {@link ASMifierAbstractVisitor}. + * + * @param name the name of the variable for this visitor in the produced + * code. + */ + protected ASMifierAbstractVisitor(final String name) { + this.name = name; + } + + /** + * Prints the ASM code that generates the given annotation. + * + * @param desc the class descriptor of the annotation class. + * @param visible <tt>true</tt> if the annotation is visible at runtime. + * @return a visitor to visit the annotation values. + */ + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + buf.setLength(0); + buf.append("{\n") + .append("av0 = ") + .append(name) + .append(".visitAnnotation("); + appendConstant(desc); + buf.append(", ").append(visible).append(");\n"); + text.add(buf.toString()); + ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0); + text.add(av.getText()); + text.add("}\n"); + return av; + } + + /** + * Prints the ASM code that generates the given attribute. + * + * @param attr an attribute. + */ + public void visitAttribute(final Attribute attr) { + buf.setLength(0); + if (attr instanceof ASMifiable) { + buf.append("{\n"); + buf.append("// ATTRIBUTE\n"); + ((ASMifiable) attr).asmify(buf, "attr", labelNames); + buf.append(name).append(".visitAttribute(attr);\n"); + buf.append("}\n"); + } else { + buf.append("// WARNING! skipped a non standard attribute of type \""); + buf.append(attr.type).append("\"\n"); + } + text.add(buf.toString()); + } + + /** + * Prints the ASM code to end the visit. + */ + public void visitEnd() { + buf.setLength(0); + buf.append(name).append(".visitEnd();\n"); + text.add(buf.toString()); + } + + /** + * Appends a string representation of the given constant to the given + * buffer. + * + * @param cst an {@link Integer}, {@link Float}, {@link Long}, + * {@link Double} or {@link String} object. May be <tt>null</tt>. + */ + void appendConstant(final Object cst) { + appendConstant(buf, cst); + } + + /** + * Appends a string representation of the given constant to the given + * buffer. + * + * @param buf a string buffer. + * @param cst an {@link Integer}, {@link Float}, {@link Long}, + * {@link Double} or {@link String} object. May be <tt>null</tt>. + */ + static void appendConstant(final StringBuffer buf, final Object cst) { + if (cst == null) { + buf.append("null"); + } else if (cst instanceof String) { + appendString(buf, (String) cst); + } else if (cst instanceof Type) { + buf.append("Type.getType(\""); + buf.append(((Type) cst).getDescriptor()); + buf.append("\")"); + } else if (cst instanceof Byte) { + buf.append("new Byte((byte)").append(cst).append(")"); + } else if (cst instanceof Boolean) { + buf.append("new Boolean(").append(cst).append(")"); + } else if (cst instanceof Short) { + buf.append("new Short((short)").append(cst).append(")"); + } else if (cst instanceof Character) { + int c = ((Character) cst).charValue(); + buf.append("new Character((char)").append(c).append(")"); + } else if (cst instanceof Integer) { + buf.append("new Integer(").append(cst).append(")"); + } else if (cst instanceof Float) { + buf.append("new Float(\"").append(cst).append("\")"); + } else if (cst instanceof Long) { + buf.append("new Long(").append(cst).append("L)"); + } else if (cst instanceof Double) { + buf.append("new Double(\"").append(cst).append("\")"); + } else if (cst instanceof byte[]) { + byte[] v = (byte[]) cst; + buf.append("new byte[] {"); + for (int i = 0; i < v.length; i++) { + buf.append(i == 0 ? "" : ",").append(v[i]); + } + buf.append("}"); + } else if (cst instanceof boolean[]) { + boolean[] v = (boolean[]) cst; + buf.append("new boolean[] {"); + for (int i = 0; i < v.length; i++) { + buf.append(i == 0 ? "" : ",").append(v[i]); + } + buf.append("}"); + } else if (cst instanceof short[]) { + short[] v = (short[]) cst; + buf.append("new short[] {"); + for (int i = 0; i < v.length; i++) { + buf.append(i == 0 ? "" : ",").append("(short)").append(v[i]); + } + buf.append("}"); + } else if (cst instanceof char[]) { + char[] v = (char[]) cst; + buf.append("new char[] {"); + for (int i = 0; i < v.length; i++) { + buf.append(i == 0 ? "" : ",") + .append("(char)") + .append((int) v[i]); + } + buf.append("}"); + } else if (cst instanceof int[]) { + int[] v = (int[]) cst; + buf.append("new int[] {"); + for (int i = 0; i < v.length; i++) { + buf.append(i == 0 ? "" : ",").append(v[i]); + } + buf.append("}"); + } else if (cst instanceof long[]) { + long[] v = (long[]) cst; + buf.append("new long[] {"); + for (int i = 0; i < v.length; i++) { + buf.append(i == 0 ? "" : ",").append(v[i]).append("L"); + } + buf.append("}"); + } else if (cst instanceof float[]) { + float[] v = (float[]) cst; + buf.append("new float[] {"); + for (int i = 0; i < v.length; i++) { + buf.append(i == 0 ? "" : ",").append(v[i]).append("f"); + } + buf.append("}"); + } else if (cst instanceof double[]) { + double[] v = (double[]) cst; + buf.append("new double[] {"); + for (int i = 0; i < v.length; i++) { + buf.append(i == 0 ? "" : ",").append(v[i]).append("d"); + } + buf.append("}"); + } + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierAnnotationVisitor.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierAnnotationVisitor.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierAnnotationVisitor.java 2007-01-07 13:55:15 UTC (rev 3034) @@ -0,0 +1,127 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.util; + +import org.objectweb.asm.AnnotationVisitor; + +/** + * An {@link AnnotationVisitor} that prints the ASM code that generates the + * annotations it visits. + * + * @author Eric Bruneton + */ +public class ASMifierAnnotationVisitor extends AbstractVisitor implements + AnnotationVisitor +{ + + /** + * Identifier of the annotation visitor variable in the produced code. + */ + protected final int id; + + /** + * Constructs a new {@link ASMifierAnnotationVisitor}. + * + * @param id identifier of the annotation visitor variable in the produced + * code. + */ + public ASMifierAnnotationVisitor(final int id) { + this.id = id; + } + + // ------------------------------------------------------------------------ + // Implementation of the AnnotationVisitor interface + // ------------------------------------------------------------------------ + + public void visit(final String name, final Object value) { + buf.setLength(0); + buf.append("av").append(id).append(".visit("); + ASMifierAbstractVisitor.appendConstant(buf, name); + buf.append(", "); + ASMifierAbstractVisitor.appendConstant(buf, value); + buf.append(");\n"); + text.add(buf.toString()); + } + + public void visitEnum( + final String name, + final String desc, + final String value) + { + buf.setLength(0); + buf.append("av").append(id).append(".visitEnum("); + ASMifierAbstractVisitor.appendConstant(buf, name); + buf.append(", "); + ASMifierAbstractVisitor.appendConstant(buf, desc); + buf.append(", "); + ASMifierAbstractVisitor.appendConstant(buf, value); + buf.append(");\n"); + text.add(buf.toString()); + } + + public AnnotationVisitor visitAnnotation( + final String name, + final String desc) + { + buf.setLength(0); + buf.append("{\n"); + buf.append("AnnotationVisitor av").append(id + 1).append(" = av"); + buf.append(id).append(".visitAnnotation("); + ASMifierAbstractVisitor.appendConstant(buf, name); + buf.append(", "); + ASMifierAbstractVisitor.appendConstant(buf, desc); + buf.append(");\n"); + text.add(buf.toString()); + ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(id + 1); + text.add(av.getText()); + text.add("}\n"); + return av; + } + + public AnnotationVisitor visitArray(final String name) { + buf.setLength(0); + buf.append("{\n"); + buf.append("AnnotationVisitor av").append(id + 1).append(" = av"); + buf.append(id).append(".visitArray("); + ASMifierAbstractVisitor.appendConstant(buf, name); + buf.append(");\n"); + text.add(buf.toString()); + ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(id + 1); + text.add(av.getText()); + text.add("}\n"); + return av; + } + + public void visitEnd() { + buf.setLength(0); + buf.append("av").append(id).append(".visitEnd();\n"); + text.add(buf.toString()); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierClassVisitor.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierClassVisitor.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierClassVisitor.java 2007-01-07 13:55:15 UTC (rev 3034) @@ -0,0 +1,607 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.util; + +import java.io.FileInputStream; +import java.io.PrintWriter; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * A {@link ClassVisitor} that prints the ASM code that generates the classes it + * visits. This class visitor can be used to quickly write ASM code to generate + * some given bytecode: <ul> <li>write the Java source code equivalent to the + * bytecode you want to generate;</li> <li>compile it with <tt>javac</tt>;</li> + * <li>make a {@link ASMifierClassVisitor} visit this compiled class (see the + * {@link #main main} method);</li> <li>edit the generated source code, if + * necessary.</li> </ul> The source code printed when visiting the + * <tt>Hello</tt> class is the following: <p> <blockquote> + * + * <pre> + * import org.objectweb.asm.*; + * + * public class HelloDump implements Opcodes { + * + * public static byte[] dump() throws Exception { + * + * ClassWriter cw = new ClassWriter(false); + * FieldVisitor fv; + * MethodVisitor mv; + * AnnotationVisitor av0; + * + * cw.visit(49, + * ACC_PUBLIC + ACC_SUPER, + * "Hello", + * null, + * "java/lang/Object", + * null); + * + * cw.visitSource("Hello.java", null); + * + * { + * mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); + * mv.visitVarInsn(ALOAD, 0); + * mv.visitMethodInsn(INVOKESPECIAL, + * "java/lang/Object", + * "<init>", + * "()V"); + * mv.visitInsn(RETURN); + * mv.visitMaxs(1, 1); + * mv.visitEnd(); + * } + * { + * mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, + * "main", + * "([Ljava/lang/String;)V", + * null, + * null); + * mv.visitFieldInsn(GETSTATIC, + * "java/lang/System", + * "out", + * "Ljava/io/PrintStream;"); + * mv.visitLdcInsn("hello"); + * mv.visitMethodInsn(INVOKEVIRTUAL, + * "java/io/PrintStream", + * "println", + * "(Ljava/lang/String;)V"); + * mv.visitInsn(RETURN); + * mv.visitMaxs(2, 1); + * mv.visitEnd(); + * } + * cw.visitEnd(); + * + * return cw.toByteArray(); + * } + * } + * + * </pre> + * + * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote> + * + * <pre> + * public class Hello { + * + * public static void main(String[] args) { + * System.out.println("hello"); + * } + * } + * </pre> + * + * </blockquote> + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public class ASMifierClassVisitor extends ASMifierAbstractVisitor implements + ClassVisitor +{ + + /** + * Pseudo access flag used to distinguish class access flags. + */ + private final static int ACCESS_CLASS = 262144; + + /** + * Pseudo access flag used to distinguish field access flags. + */ + private final static int ACCESS_FIELD = 524288; + + /** + * Pseudo access flag used to distinguish inner class flags. + */ + private static final int ACCESS_INNER = 1048576; + + /** + * The print writer to be used to print the class. + */ + protected final PrintWriter pw; + + /** + * Prints the ASM source code to generate the given class to the standard + * output. <p> Usage: ASMifierClassVisitor [-debug] <fully qualified + * class name or class file name> + * + * @param args the command line arguments. + * + * @throws Exception if the class cannot be found, or if an IO exception + * occurs. + */ + public static void main(final String[] args) throws Exception { + int i = 0; + boolean skipDebug = true; + + boolean ok = true; + if (args.length < 1 || args.length > 2) { + ok = false; + } + if (ok && args[0].equals("-debug")) { + i = 1; + skipDebug = false; + if (args.length != 2) { + ok = false; + } + } + if (!ok) { + System.err.println("Prints the ASM code to generate the given class."); + System.err.println("Usage: ASMifierClassVisitor [-debug] " + + "<fully qualified class name or class file name>"); + return; + } + ClassReader cr; + if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1 + || args[i].indexOf('/') > -1) { + cr = new ClassReader(new FileInputStream(args[i])); + } else { + cr = new ClassReader(args[i]); + } + cr.accept(new ASMifierClassVisitor(new PrintWriter(System.out)), + getDefaultAttributes(), + skipDebug); + } + + /** + * Constructs a new {@link ASMifierClassVisitor} object. + * + * @param pw the print writer to be used to print the class. + */ + public ASMifierClassVisitor(final PrintWriter pw) { + super("cw"); + this.pw = pw; + } + + // ------------------------------------------------------------------------ + // Implementation of the ClassVisitor interface + // ------------------------------------------------------------------------ + + public void visit( + final int version, + final int access, + final String name, + final String signature, + final String superName, + final String[] interfaces) + { + String simpleName; + int n = name.lastIndexOf('/'); + if (n != -1) { + text.add("package asm." + name.substring(0, n).replace('/', '.') + + ";\n"); + simpleName = name.substring(n + 1); + } else { + simpleName = name; + } + text.add("import java.util.*;\n"); + text.add("import org.objectweb.asm.*;\n"); + text.add("import org.objectweb.asm.attrs.*;\n"); + text.add("public class " + simpleName + "Dump implements Opcodes {\n\n"); + text.add("public static byte[] dump () throws Exception {\n\n"); + text.add("ClassWriter cw = new ClassWriter(false);\n"); + text.add("FieldVisitor fv;\n"); + text.add("MethodVisitor mv;\n"); + text.add("AnnotationVisitor av0;\n\n"); + + buf.setLength(0); + buf.append("cw.visit("); + switch (version) { + case Opcodes.V1_1: + buf.append("V1_1"); + break; + case Opcodes.V1_2: + buf.append("V1_2"); + break; + case Opcodes.V1_3: + buf.append("V1_3"); + break; + case Opcodes.V1_4: + buf.append("V1_4"); + break; + case Opcodes.V1_5: + buf.append("V1_5"); + break; + case Opcodes.V1_6: + buf.append("V1_6"); + break; + default: + buf.append(version); + break; + } + buf.append(", "); + appendAccess(access | ACCESS_CLASS); + buf.append(", "); + appendConstant(name); + buf.append(", "); + appendConstant(signature); + buf.append(", "); + appendConstant(superName); + buf.append(", "); + if (interfaces != null && interfaces.length > 0) { + buf.append("new String[] {"); + for (int i = 0; i < interfaces.length; ++i) { + buf.append(i == 0 ? " " : ", "); + appendConstant(interfaces[i]); + } + buf.append(" }"); + } else { + buf.append("null"); + } + buf.append(");\n\n"); + text.add(buf.toString()); + } + + public void visitSource(final String file, final String debug) { + buf.setLength(0); + buf.append("cw.visitSource("); + appendConstant(file); + buf.append(", "); + appendConstant(debug); + buf.append(");\n\n"); + text.add(buf.toString()); + } + + public void visitOuterClass( + final String owner, + final String name, + final String desc) + { + buf.setLength(0); + buf.append("cw.visitOuterClass("); + appendConstant(owner); + buf.append(", "); + appendConstant(name); + buf.append(", "); + appendConstant(desc); + buf.append(");\n\n"); + text.add(buf.toString()); + } + + public void visitInnerClass( + final String name, + final String outerName, + final String innerName, + final int access) + { + buf.setLength(0); + buf.append("cw.visitInnerClass("); + appendConstant(name); + buf.append(", "); + appendConstant(outerName); + buf.append(", "); + appendConstant(innerName); + buf.append(", "); + appendAccess(access | ACCESS_INNER); + buf.append(");\n\n"); + text.add(buf.toString()); + } + + public FieldVisitor visitField( + final int access, + final String name, + final String desc, + final String signature, + final Object value) + { + buf.setLength(0); + buf.append("{\n"); + buf.append("fv = cw.visitField("); + appendAccess(access | ACCESS_FIELD); + buf.append(", "); + appendConstant(name); + buf.append(", "); + appendConstant(desc); + buf.append(", "); + appendConstant(signature); + buf.append(", "); + appendConstant(value); + buf.append(");\n"); + text.add(buf.toString()); + ASMifierFieldVisitor aav = new ASMifierFieldVisitor(); + text.add(aav.getText()); + text.add("}\n"); + return aav; + } + + public MethodVisitor visitMethod( + final int access, + final String name, + final String desc, + final String signature, + final String[] exceptions) + { + buf.setLength(0); + buf.append("{\n"); + buf.append("mv = cw.visitMethod("); + appendAccess(access); + buf.append(", "); + appendConstant(name); + buf.append(", "); + appendConstant(desc); + buf.append(", "); + appendConstant(signature); + buf.append(", "); + if (exceptions != null && exceptions.length > 0) { + buf.append("new String[] {"); + for (int i = 0; i < exceptions.length; ++i) { + buf.append(i == 0 ? " " : ", "); + appendConstant(exceptions[i]); + } + buf.append(" }"); + } else { + buf.append("null"); + } + buf.append(");\n"); + text.add(buf.toString()); + ASMifierMethodVisitor acv = new ASMifierMethodVisitor(); + text.add(acv.getText()); + text.add("}\n"); + return acv; + } + + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + buf.setLength(0); + buf.append("{\n"); + buf.append("av0 = cw.visitAnnotation("); + appendConstant(desc); + buf.append(", "); + buf.append(visible); + buf.append(");\n"); + text.add(buf.toString()); + ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0); + text.add(av.getText()); + text.add("}\n"); + return av; + } + + public void visitEnd() { + text.add("cw.visitEnd();\n\n"); + text.add("return cw.toByteArray();\n"); + text.add("}\n"); + text.add("}\n"); + printList(pw, text); + pw.flush(); + } + + // ------------------------------------------------------------------------ + // Utility methods + // ------------------------------------------------------------------------ + + /** + * Appends a string representation of the given access modifiers to {@link + * #buf buf}. + * + * @param access some access modifiers. + */ + void appendAccess(final int access) { + boolean first = true; + if ((access & Opcodes.ACC_PUBLIC) != 0) { + buf.append("ACC_PUBLIC"); + first = false; + } + if ((access & Opcodes.ACC_PRIVATE) != 0) { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_PRIVATE"); + first = false; + } + if ((access & Opcodes.ACC_PROTECTED) != 0) { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_PROTECTED"); + first = false; + } + if ((access & Opcodes.ACC_FINAL) != 0) { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_FINAL"); + first = false; + } + if ((access & Opcodes.ACC_STATIC) != 0) { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_STATIC"); + first = false; + } + if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) { + if (!first) { + buf.append(" + "); + } + if ((access & ACCESS_CLASS) != 0) { + buf.append("ACC_SUPER"); + } else { + buf.append("ACC_SYNCHRONIZED"); + } + first = false; + } + if ((access & Opcodes.ACC_VOLATILE) != 0 + && (access & ACCESS_FIELD) != 0) + { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_VOLATILE"); + first = false; + } + if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0 + && (access & ACCESS_FIELD) == 0) + { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_BRIDGE"); + first = false; + } + if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0 + && (access & ACCESS_FIELD) == 0) + { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_VARARGS"); + first = false; + } + if ((access & Opcodes.ACC_TRANSIENT) != 0 + && (access & ACCESS_FIELD) != 0) + { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_TRANSIENT"); + first = false; + } + if ((access & Opcodes.ACC_NATIVE) != 0 && (access & ACCESS_CLASS) == 0 + && (access & ACCESS_FIELD) == 0) + { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_NATIVE"); + first = false; + } + if ((access & Opcodes.ACC_ENUM) != 0 + && ((access & ACCESS_CLASS) != 0 + || (access & ACCESS_FIELD) != 0 || (access & ACCESS_INNER) != 0)) + { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_ENUM"); + first = false; + } + if ((access & Opcodes.ACC_ANNOTATION) != 0 + && ((access & ACCESS_CLASS) != 0)) + { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_ANNOTATION"); + first = false; + } + if ((access & Opcodes.ACC_ABSTRACT) != 0) { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_ABSTRACT"); + first = false; + } + if ((access & Opcodes.ACC_INTERFACE) != 0) { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_INTERFACE"); + first = false; + } + if ((access & Opcodes.ACC_STRICT) != 0) { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_STRICT"); + first = false; + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_SYNTHETIC"); + first = false; + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_DEPRECATED"); + first = false; + } + if (first) { + buf.append("0"); + } + } + + /** + * Appends a string representation of the given constant to the given + * buffer. + * + * @param buf a string buffer. + * @param cst an {@link java.lang.Integer Integer}, {@link java.lang.Float + * Float}, {@link java.lang.Long Long}, + * {@link java.lang.Double Double} or {@link String String} object. + * May be <tt>null</tt>. + */ + static void appendConstant(final StringBuffer buf, final Object cst) { + if (cst == null) { + buf.append("null"); + } else if (cst instanceof String) { + AbstractVisitor.appendString(buf, (String) cst); + } else if (cst instanceof Type) { + buf.append("Type.getType(\"") + .append(((Type) cst).getDescriptor()) + .append("\")"); + } else if (cst instanceof Integer) { + buf.append("new Integer(").append(cst).append(")"); + } else if (cst instanceof Float) { + buf.append("new Float(\"").append(cst).append("\")"); + } else if (cst instanceof Long) { + buf.append("new Long(").append(cst).append("L)"); + } else if (cst instanceof Double) { + buf.append("new Double(\"").append(cst).append("\")"); + } + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierFieldVisitor.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierFieldVisitor.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierFieldVisitor.java 2007-01-07 13:55:15 UTC (rev 3034) @@ -0,0 +1,50 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.util; + +import org.objectweb.asm.FieldVisitor; + +/** + * A {@link FieldVisitor} that prints the ASM code that generates the fields it + * visits. + * + * @author Eric Bruneton + */ +public class ASMifierFieldVisitor extends ASMifierAbstractVisitor implements + FieldVisitor +{ + + /** + * Constructs a new {@link ASMifierFieldVisitor}. + */ + public ASMifierFieldVisitor() { + super("fv"); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierMethodVisitor.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierMethodVisitor.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/util/ASMifierMethodVisitor.java 2007-01-07 13:55:15 UTC (rev 3034) @@ -0,0 +1,347 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.util; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; + +import java.util.HashMap; + +/** + * A {@link MethodVisitor} that prints the ASM code that generates the methods + * it visits. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public class ASMifierMethodVisitor extends ASMifierAbstractVisitor implements + MethodVisitor +{ + + /** + * Constructs a new {@link ASMifierMethodVisitor} object. + */ + public ASMifierMethodVisitor() { + super("mv"); + this.labelNames = new HashMap(); + } + + public AnnotationVisitor visitAnnotationDefault() { + buf.setLength(0); + buf.append("{\n").append("av0 = mv.visitAnnotationDefault();\n"); + text.add(buf.toString()); + ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0); + text.add(av.getText()); + text.add("}\n"); + return av; + } + + public AnnotationVisitor visitParameterAnnotation( + final int parameter, + final String desc, + final boolean visible) + { + buf.setLength(0); + buf.append("{\n") + .append("av0 = mv.visitParameterAnnotation(") + .append(parameter) + .append(", "); + appendConstant(desc); + buf.append(", ").append(visible).append(");\n"); + text.add(buf.toString()); + ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0); + text.add(av.getText()); + text.add("}\n"); + return av; + } + + public void visitCode() { + text.add("mv.visitCode();\n"); + } + + public void visitInsn(final int opcode) { + buf.setLength(0); + buf.append("mv.visitInsn(").append(OPCODES[opcode]).append(");\n"); + text.add(buf.toString()); + } + + public void visitIntInsn(final int opcode, final int operand) { + buf.setLength(0); + buf.append("mv.visitIntInsn(") + .append(OPCODES[opcode]) + .append(", ") + .append(opcode == Opcodes.NEWARRAY + ? TYPES[operand] + : Integer.toString(operand)) + .append(");\n"); + text.add(buf.toString()); + } + + public void visitVarInsn(final int opcode, final int var) { + buf.setLength(0); + buf.append("mv.visitVarInsn(") + .append(OPCODES[opcode]) + .append(", ") + .append(var) + .append(");\n"); + text.add(buf.toString()); + } + + public void visitTypeInsn(final int opcode, final String desc) { + buf.setLength(0); + buf.append("mv.visitTypeInsn(").append(OPCODES[opcode]).append(", "); + appendConstant(desc); + buf.append(");\n"); + text.add(buf.toString()); + } + + public void visitFieldInsn( + final int opcode, + final String owner, + final String name, + final String desc) + { + buf.setLength(0); + buf.append("mv.visitFieldInsn(").append(OPCODES[opcode]).append(", "); + appendConstant(owner); + buf.append(", "); + appendConstant(name); + buf.append(", "); + appendConstant(desc); + buf.append(");\n"); + text.add(buf.toString()); + } + + public void visitMethodInsn( + final int opcode, + final String owner, + final String name, + final String desc) + { + buf.setLength(0); + buf.append("mv.visitMethodInsn(").append(OPCODES[opcode]).append(", "); + appendConstant(owner); + buf.append(", "); + appendConstant(name); + buf.append(", "); + appendConstant(desc); + buf.append(");\n"); + text.add(buf.toString()); + } + + public void visitJumpInsn(final int opcode, final Label label) { + buf.setLength(0); + declareLabel(label); + buf.append("mv.visitJumpInsn(").append(OPCODES[opcode]).append(", "); + appendLabel(label); + buf.append(");\n"); + text.add(buf.toString()); + } + + public void visitLabel(final Label label) { + buf.setLength(0); + declareLabel(label); + buf.append("mv.visitLabel("); + appendLabel(label); + buf.append(");\n"); + text.add(buf.toString()); + } + + public void visitLdcInsn(final Object cst) { + buf.setLength(0); + buf.append("mv.visitLdcInsn("); + appendConstant(cst); + buf.append(");\n"); + text.add(buf.toString()); + } + + public void visitIincInsn(final int var, final int increment) { + buf.setLength(0); + buf.append("mv.visitIincInsn(") + .append(var) + .append(", ") + .append(increment) + .append(");\n"); + text.add(buf.toString()); + } + + public void visitTableSwitchInsn( + final int min, + final int max, + final Label dflt, + final Label labels[]) + { + buf.setLength(0); + for (int i = 0; i < labels.length; ++i) { + declareLabel(labels[i]); + } + declareLabel(dflt); + + buf.append("mv.visitTableSwitchInsn(") + .append(min) + .append(", ") + .append(max) + .append(", "); + appendLabel(dflt); + buf.append(", new Label[] {"); + for (int i = 0; i < labels.length; ++i) { + buf.append(i == 0 ? " " : ", "); + appendLabel(labels[i]); + } + buf.append(" });\n"); + text.add(buf.toString()); + } + + public void visitLookupSwitchInsn( + final Label dflt, + final int keys[], + final Label labels[]) + { + buf.setLength(0); + for (int i = 0; i < labels.length; ++i) { + declareLabel(labels[i]); + } + declareLabel(dflt); + + buf.append("mv.visitLookupSwitchInsn("); + appendLabel(dflt); + buf.append(", new int[] {"); + for (int i = 0; i < keys.length; ++i) { + buf.append(i == 0 ? " " : ", ").append(keys[i]); + } + buf.append(" }, new Label[] {"); + for (int i = 0; i < labels.length; ++i) { + buf.append(i == 0 ? " " : ", "); + appendLabel(labels[i]); + } + buf.append(" });\n"); + text.add(buf.toString()); + } + + public void visitMultiANewArrayInsn(final String desc, final int dims) { + buf.setLength(0); + buf.append("mv.visitMultiANewArrayInsn("); + appendConstant(desc); + buf.append(", ").append(dims).append(");\n"); + text.add(buf.toString()); + } + + public void visitTryCatchBlock( + final Label start, + final Label end, + final Label handler, + final String type) + { + buf.setLength(0); + declareLabel(start); + declareLabel(end); + declareLabel(handler); + buf.append("mv.visitTryCatchBlock("); + appendLabel(start); + buf.append(", "); + appendLabel(end); + buf.append(", "); + appendLabel(handler); + buf.append(", "); + appendConstant(type); + buf.append(");\n"); + text.add(buf.toString()); + } + + public void visitLocalVariable( + final String name, + final String desc, + final String signature, + final Label start, + final Label end, + final int index) + { + buf.setLength(0); + buf.append("mv.visitLocalVariable("); + appendConstant(name); + buf.append(", "); + appendConstant(desc); + buf.append(", "); + appendConstant(signature); + buf.append(", "); + appendLabel(start); + buf.append(", "); + appendLabel(end); + buf.append(", ").append(index).append(");\n"); + text.add(buf.toString()); + } + + public void visitLineNumber(final int line, final Label start) { + buf.setLength(0); + buf.append("mv.visitLineNumber(").append(line).append(", "); + appendLabel(start); + buf.append(");\n"); + text.add(buf.toString()); + } + + public void visitMaxs(final int maxStack, final int maxLocals) { + buf.setLength(0); + buf.append("mv.visitMaxs(") + .append(maxStack) + .append(", ") + .append(maxLocals) + .append(");\n"); + text.add(buf.toString()); + } + + /** + * Appends a declaration of the given label to {@link #buf buf}. This + * declaration is of the form "Label lXXX = new Label();". Does nothing if + * the given label has already been declared. + * + * @param l a label. + */ + private void declareLabel(final Label l) { + String name = (String) labelNames.get(l); + if (name == null) { + name = "l" + labelNames.size(); + labelNames.put(l, name); + buf.append("Label ").append(name).append(" = new Label();\n"); + } + } + + /** + * Appends the name of the given label to {@link #buf buf}. The given label + * <i>must</i> already have a name. One way to ensure this is to always + * call {@link #declareLabel declared} before calling this method. + * + * @param l a label. + */ + private void appendLabel(final Label l) { + buf.append((String) labelNames.get(l)); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/util/AbstractVisitor.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/util/AbstractVisitor.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/util/AbstractVisitor.java 2007-01-07 13:55:15 UTC (rev 3034) @@ -0,0 +1,201 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.util; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import org.objectweb.asm.Attribute; +import org.objectweb.asm.util.attrs.ASMStackMapAttribute; +import org.objectweb.asm.util.attrs.ASMStackMapTableAttribute; + +/** + * An abstract visitor. + * + * @author Eric Bruneton + */ +public abstract class AbstractVisitor { + + /** + * The names of the Java Virtual Machine opcodes. + */ + public final static String[] OPCODES; + /** + * Types for <code>operand</code> parameter of the + * {@link org.objectweb.asm.MethodVisitor#visitIntInsn} method when + * <code>opcode</code> is <code>NEWARRAY</code>. + */ + public final static String[] TYPES; + + static { + String s = "NOP,ACONST_NULL,ICONST_M1,ICONST_0,ICONST_1,ICONST_2," + + "ICONST_3,ICONST_4,ICONST_5,LCONST_0,LCONST_1,FCONST_0," + + "FCONST_1,FCONST_2,DCONST_0,DCONST_1,BIPUSH,SIPUSH,LDC,,," + + "ILOAD,LLOAD,FLOAD,DLOAD,ALOAD,,,,,,,,,,,,,,,,,,,,,IALOAD," + + "LALOAD,FALOAD,DALOAD,AALOAD,BALOAD,CALOAD,SALOAD,ISTORE," + + "LSTORE,FSTORE,DSTORE,ASTORE,,,,,,,,,,,,,,,,,,,,,IASTORE," + + "LASTORE,FASTORE,DASTORE,AASTORE,BASTORE,CASTORE,SASTORE,POP," + + "POP2,DUP,DUP_X1,DUP_X2,DUP2,DUP2_X1,DUP2_X2,SWAP,IADD,LADD," + + "FADD,DADD,ISUB,LSUB,FSUB,DSUB,IMUL,LMUL,FMUL,DMUL,IDIV,LDIV," + + "FDIV,DDIV,IREM,LREM,FREM,DREM,INEG,LNEG,FNEG,DNEG,ISHL,LSHL," + + "ISHR,LSHR,IUSHR,LUSHR,IAND,LAND,IOR,LOR,IXOR,LXOR,IINC,I2L," + + "I2F,I2D,L2I,L2F,L2D,F2I,F2L,F2D,D2I,D2L,D2F,I2B,I2C,I2S,LCMP," + + "FCMPL,FCMPG,DCMPL,DCMPG,IFEQ,IFNE,IFLT,IFGE,IFGT,IFLE," + + "IF_ICMPEQ,IF_ICMPNE,IF_ICMPLT,IF_ICMPGE,IF_ICMPGT,IF_ICMPLE," + + "IF_ACMPEQ,IF_ACMPNE,GOTO,JSR,RET,TABLESWITCH,LOOKUPSWITCH," + + "IRETURN,LRETURN,FRETURN,DRETURN,ARETURN,RETURN,GETSTATIC," + + "PUTSTATIC,GETFIELD,PUTFIELD,INVOKEVIRTUAL,INVOKESPECIAL," + + "INVOKESTATIC,INVOKEINTERFACE,,NEW,NEWARRAY,ANEWARRAY," + + "ARRAYLENGTH,ATHROW,CHECKCAST,INSTANCEOF,MONITORENTER," + + "MONITOREXIT,,MULTIANEWARRAY,IFNULL,IFNONNULL,"; + OPCODES = new String[200]; + int i = 0; + int j = 0; + int l; + while ((l = s.indexOf(',', j)) > 0) { + OPCODES[i++] = j + 1 == l ? null : s.substring(j, l); + j = l + 1; + } + + s = "T_BOOLEAN,T_CHAR,T_FLOAT,T_DOUBLE,T_BYTE,T_SHORT,T_INT,T_LONG,"; + TYPES = new String[12]; + j = 0; + i = 4; + while ((l = s.indexOf(',', j)) > 0) { + TYPES[i++] = s.substring(j, l); + j = l + 1; + } + } + + /** + * The text to be printed. Since the code of methods is not necessarily + * visited in sequential order, one method after the other, but can be + * interlaced (some instructions from method one, then some instructions + * from method two, then some instructions from method one again...), it is + * not possible to print the visited instructions directly to a sequential + * stream. A class is therefore printed in a two steps process: a string + * tree is constructed during the visit, and printed to a sequential stream + * at the end of the visit. This string tree is stored in this field, as a + * string list that can contain other string lists, which can themselves + * contain other string lists, and so on. + */ + public final List text; + + /** + * A buffer that can be used to create strings. + */ + protected final StringBuffer buf; + + /** + * Constructs a new {@link AbstractVisitor}. + */ + protected AbstractVisitor() { + this.text = new ArrayList(); + this.buf = new StringBuffer(); + } + + /** + * Returns the text printed by this visitor. + * + * @return the text printed by this visitor. + */ + public List getText() { + return text; + } + + /** + * Appends a quoted string to a given buffer. + * + * @param buf the buffer where the string must be added. + * @param s the string to be added. + */ + public static void appendString(final StringBuffer buf, final String s) { + buf.append("\""); + for (int i = 0; i < s.length(); ++i) { + char c = s.charAt(i); + if (c == '\n') { + buf.append("\\n"); + } else if (c == '\r') { + buf.append("\\r"); + } else if (c == '\\') { + buf.append("\\\\"); + } else if (c == '"') { + buf.append("\\\""); + } else if (c < 0x20 || c > 0x7f) { + buf.append("\\u"); + if (c < 0x10) { + buf.append("000"); + } else if (c < 0x100) { + buf.append("00"); + } else if (c < 0x1000) { + buf.append("0"); + } + buf.append(Integer.toString(c, 16)); + } else { + buf.append(c); + } + } + buf.append("\""); + } + + /** + * Prints the given string tree. + * + * @param pw the writer to be used to print the tree. + * @param l a string tree, i.e., a string list that can contain other string + * lists, and so on recursively. + */ + void printList(final PrintWriter pw, final List l) { + for (int i = 0; i < l.size(); ++i) { + Object o = l.get(i); + if (o instanceof List) { + printList(pw, (List) o); + } else { + pw.print(o.toString()); + } + } + } + + /** + * Returns the default {@link ASMifiable} prototypes. + * + * @return the default {@link ASMifiable} prototypes. + */ + public static Attribute[] getDefaultAttributes() { + try { + return new Attribute[] { + new ASMStackMapAttribute(), + new ASMStackMapTableAttribute() }; + } catch (Exception e) { + return new Attribute[0]; + } + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/util/CheckAnnotationAdapter.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/util/CheckAnnotationAdapter.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/util/CheckAnnotationAdapter.java 2007-01-07 13:55:15 UTC (rev 3034) @@ -0,0 +1,125 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with o... [truncated message content] |
From: <ls...@us...> - 2007-01-07 13:53:12
|
Revision: 3033 http://jnode.svn.sourceforge.net/jnode/?rev=3033&view=rev Author: lsantha Date: 2007-01-07 05:53:11 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Added Paths: ----------- trunk/core/src/classpath/org/org/objectweb/asm/tree/AbstractInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/AnnotationNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/ClassNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/FieldInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/FieldNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/IincInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/InnerClassNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/InsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/IntInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/JumpInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/LabelNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/LdcInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/LineNumberNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/LocalVariableNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/LookupSwitchInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/MemberNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/MethodInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/MethodNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/MultiANewArrayInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/TableSwitchInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/TryCatchBlockNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/TypeInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/VarInsnNode.java trunk/core/src/classpath/org/org/objectweb/asm/tree/package.html Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/AbstractInsnNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/AbstractInsnNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/AbstractInsnNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,143 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.MethodVisitor; + +/** + * A node that represents a bytecode instruction. + * + * @author Eric Bruneton + */ +public abstract class AbstractInsnNode { + + /** + * The type of {@link InsnNode} instructions. + */ + public final static int INSN = 0; + + /** + * The type of {@link IntInsnNode} instructions. + */ + public final static int INT_INSN = 1; + + /** + * The type of {@link VarInsnNode} instructions. + */ + public final static int VAR_INSN = 2; + + /** + * The type of {@link TypeInsnNode} instructions. + */ + public final static int TYPE_INSN = 3; + + /** + * The type of {@link FieldInsnNode} instructions. + */ + public final static int FIELD_INSN = 4; + + /** + * The type of {@link MethodInsnNode} instructions. + */ + public final static int METHOD_INSN = 5; + + /** + * The type of {@link JumpInsnNode} instructions. + */ + public final static int JUMP_INSN = 6; + + /** + * The type of {@link LabelNode} "instructions". + */ + public final static int LABEL = 7; + + /** + * The type of {@link LdcInsnNode} instructions. + */ + public final static int LDC_INSN = 8; + + /** + * The type of {@link IincInsnNode} instructions. + */ + public final static int IINC_INSN = 9; + + /** + * The type of {@link TableSwitchInsnNode} instructions. + */ + public final static int TABLESWITCH_INSN = 10; + + /** + * The type of {@link LookupSwitchInsnNode} instructions. + */ + public final static int LOOKUPSWITCH_INSN = 11; + + /** + * The type of {@link MultiANewArrayInsnNode} instructions. + */ + public final static int MULTIANEWARRAY_INSN = 12; + + /** + * The opcode of this instruction. + */ + protected int opcode; + + /** + * Constructs a new {@link AbstractInsnNode}. + * + * @param opcode the opcode of the instruction to be constructed. + */ + protected AbstractInsnNode(final int opcode) { + this.opcode = opcode; + } + + /** + * Returns the opcode of this instruction. + * + * @return the opcode of this instruction. + */ + public int getOpcode() { + return opcode; + } + + /** + * Returns the type of this instruction. + * + * @return the type of this instruction, i.e. one the constants defined in + * this class. + */ + public abstract int getType(); + + /** + * Makes the given code visitor visit this instruction. + * + * @param cv a code visitor. + */ + public abstract void accept(final MethodVisitor cv); +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/AnnotationNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/AnnotationNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/AnnotationNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,187 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import java.util.ArrayList; +import java.util.List; + +import org.objectweb.asm.AnnotationVisitor; + +/** + * A node that represents an annotationn. + * + * @author Eric Bruneton + */ +public class AnnotationNode implements AnnotationVisitor { + + /** + * The class descriptor of the annotation class. + */ + public String desc; + + /** + * The name value pairs of this annotation. Each name value pair is stored + * as two consecutive elements in the list. The name is a {@link String}, + * and the value may be a {@link Byte}, {@link Boolean}, {@link Character}, + * {@link Short}, {@link Integer}, {@link Long}, {@link Float}, + * {@link Double}, {@link String} or {@link org.objectweb.asm.Type}, or an + * two elements String array (for enumeration values), a + * {@link AnnotationNode}, or a {@link List} of values of one of the + * preceding types. The list may be <tt>null</tt> if there is no name + * value pair. + */ + public List values; + + /** + * Constructs a new {@link AnnotationNode}. + * + * @param desc the class descriptor of the annotation class. + */ + public AnnotationNode(final String desc) { + this.desc = desc; + } + + /** + * Constructs a new {@link AnnotationNode} to visit an array value. + * + * @param values where the visited values must be stored. + */ + AnnotationNode(final List values) { + this.values = values; + } + + // ------------------------------------------------------------------------ + // Implementation of the AnnotationVisitor interface + // ------------------------------------------------------------------------ + + public void visit(final String name, final Object value) { + if (values == null) { + values = new ArrayList(this.desc != null ? 2 : 1); + } + if (this.desc != null) { + values.add(name); + } + values.add(value); + } + + public void visitEnum( + final String name, + final String desc, + final String value) + { + if (values == null) { + values = new ArrayList(this.desc != null ? 2 : 1); + } + if (this.desc != null) { + values.add(name); + } + values.add(new String[] { desc, value }); + } + + public AnnotationVisitor visitAnnotation( + final String name, + final String desc) + { + if (values == null) { + values = new ArrayList(this.desc != null ? 2 : 1); + } + if (this.desc != null) { + values.add(name); + } + AnnotationNode annotation = new AnnotationNode(desc); + values.add(annotation); + return annotation; + } + + public AnnotationVisitor visitArray(final String name) { + if (values == null) { + values = new ArrayList(this.desc != null ? 2 : 1); + } + if (this.desc != null) { + values.add(name); + } + List array = new ArrayList(); + values.add(array); + return new AnnotationNode(array); + } + + public void visitEnd() { + } + + // ------------------------------------------------------------------------ + // Accept methods + // ------------------------------------------------------------------------ + + /** + * Makes the given visitor visit this annotation. + * + * @param av an annotation visitor. + */ + public void accept(final AnnotationVisitor av) { + if (values != null) { + for (int i = 0; i < values.size(); i += 2) { + String name = (String) values.get(i); + Object value = values.get(i + 1); + accept(av, name, value); + } + } + av.visitEnd(); + } + + /** + * Makes the given visitor visit a given annotation value. + * + * @param av an annotation visitor. + * @param name the value name. + * @param value the actual value. + */ + static void accept( + final AnnotationVisitor av, + final String name, + final Object value) + { + if (value instanceof String[]) { + String[] typeconst = (String[]) value; + av.visitEnum(name, typeconst[0], typeconst[1]); + } else if (value instanceof AnnotationNode) { + AnnotationNode an = (AnnotationNode) value; + an.accept(av.visitAnnotation(name, an.desc)); + } else if (value instanceof List) { + AnnotationVisitor v = av.visitArray(name); + List array = (List) value; + for (int j = 0; j < array.size(); ++j) { + accept(v, null, array.get(j)); + } + v.visitEnd(); + } else { + av.visit(name, value); + } + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/ClassNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/ClassNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/ClassNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,283 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.FieldVisitor; + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +/** + * A node that represents a class. + * + * @author Eric Bruneton + */ +public class ClassNode extends MemberNode implements ClassVisitor { + + /** + * The class version. + */ + public int version; + + /** + * The class's access flags (see {@link org.objectweb.asm.Opcodes}). This + * field also indicates if the class is deprecated. + */ + public int access; + + /** + * The internal name of the class (see + * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). + */ + public String name; + + /** + * The signature of the class. Mayt be <tt>null</tt>. + */ + public String signature; + + /** + * The internal of name of the super class (see + * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). For + * interfaces, the super class is {@link Object}. May be <tt>null</tt>, + * but only for the {@link Object} class. + */ + public String superName; + + /** + * The internal names of the class's interfaces (see + * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). This + * list is a list of {@link String} objects. + */ + public List interfaces; + + /** + * The name of the source file from which this class was compiled. May be + * <tt>null</tt>. + */ + public String sourceFile; + + /** + * Debug information to compute the correspondance between source and + * compiled elements of the class. May be <tt>null</tt>. + */ + public String sourceDebug; + + /** + * The internal name of the enclosing class of the class. May be + * <tt>null</tt>. + */ + public String outerClass; + + /** + * The name of the method that contains the class, or <tt>null</tt> if the + * class is not enclosed in a method. + */ + public String outerMethod; + + /** + * The descriptor of the method that contains the class, or <tt>null</tt> + * if the class is not enclosed in a method. + */ + public String outerMethodDesc; + + /** + * Informations about the inner classes of this class. This list is a list + * of {@link InnerClassNode} objects. + * + * @associates org.objectweb.asm.tree.InnerClassNode + */ + public List innerClasses; + + /** + * The fields of this class. This list is a list of {@link FieldNode} + * objects. + * + * @associates org.objectweb.asm.tree.FieldNode + */ + public List fields; + + /** + * The methods of this class. This list is a list of {@link MethodNode} + * objects. + * + * @associates org.objectweb.asm.tree.MethodNode + */ + public List methods; + + /** + * Constructs a new {@link ClassNode}. + */ + public ClassNode() { + this.interfaces = new ArrayList(); + this.innerClasses = new ArrayList(); + this.fields = new ArrayList(); + this.methods = new ArrayList(); + } + + // ------------------------------------------------------------------------ + // Implementation of the ClassVisitor interface + // ------------------------------------------------------------------------ + + public void visit( + final int version, + final int access, + final String name, + final String signature, + final String superName, + final String[] interfaces) + { + this.version = version; + this.access = access; + this.name = name; + this.signature = signature; + this.superName = superName; + if (interfaces != null) { + this.interfaces.addAll(Arrays.asList(interfaces)); + } + } + + public void visitSource(final String file, final String debug) { + sourceFile = file; + sourceDebug = debug; + } + + public void visitOuterClass( + final String owner, + final String name, + final String desc) + { + outerClass = owner; + outerMethod = name; + outerMethodDesc = desc; + } + + public void visitInnerClass( + final String name, + final String outerName, + final String innerName, + final int access) + { + InnerClassNode icn = new InnerClassNode(name, + outerName, + innerName, + access); + innerClasses.add(icn); + } + + public FieldVisitor visitField( + final int access, + final String name, + final String desc, + final String signature, + final Object value) + { + FieldNode fn = new FieldNode(access, name, desc, signature, value); + fields.add(fn); + return fn; + } + + public MethodVisitor visitMethod( + final int access, + final String name, + final String desc, + final String signature, + final String[] exceptions) + { + MethodNode mn = new MethodNode(access, + name, + desc, + signature, + exceptions); + methods.add(mn); + return mn; + } + + public void visitEnd() { + } + + // ------------------------------------------------------------------------ + // Accept method + // ------------------------------------------------------------------------ + + /** + * Makes the given class visitor visit this class. + * + * @param cv a class visitor. + */ + public void accept(final ClassVisitor cv) { + // visits header + String[] interfaces = new String[this.interfaces.size()]; + this.interfaces.toArray(interfaces); + cv.visit(version, access, name, signature, superName, interfaces); + // visits source + if (sourceFile != null || sourceDebug != null) { + cv.visitSource(sourceFile, sourceDebug); + } + // visits outer class + if (outerClass != null) { + cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc); + } + // visits attributes + int i, n; + n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); + for (i = 0; i < n; ++i) { + AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i); + an.accept(cv.visitAnnotation(an.desc, true)); + } + n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); + for (i = 0; i < n; ++i) { + AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i); + an.accept(cv.visitAnnotation(an.desc, false)); + } + n = attrs == null ? 0 : attrs.size(); + for (i = 0; i < n; ++i) { + cv.visitAttribute((Attribute) attrs.get(i)); + } + // visits inner classes + for (i = 0; i < innerClasses.size(); ++i) { + ((InnerClassNode) innerClasses.get(i)).accept(cv); + } + // visits fields + for (i = 0; i < fields.size(); ++i) { + ((FieldNode) fields.get(i)).accept(cv); + } + // visits methods + for (i = 0; i < methods.size(); ++i) { + ((MethodNode) methods.get(i)).accept(cv); + } + // visits end + cv.visitEnd(); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/FieldInsnNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/FieldInsnNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/FieldInsnNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,97 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.MethodVisitor; + +/** + * A node that represents a field instruction. A field instruction is an + * instruction that loads or stores the value of a field of an object. + * + * @author Eric Bruneton + */ +public class FieldInsnNode extends AbstractInsnNode { + + /** + * The internal name of the field's owner class (see + * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). + */ + public String owner; + + /** + * The field's name. + */ + public String name; + + /** + * The field's descriptor (see {@link org.objectweb.asm.Type}). + */ + public String desc; + + /** + * Constructs a new {@link FieldInsnNode}. + * + * @param opcode the opcode of the type instruction to be constructed. This + * opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. + * @param owner the internal name of the field's owner class (see + * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). + * @param name the field's name. + * @param desc the field's descriptor (see {@link org.objectweb.asm.Type}). + */ + public FieldInsnNode( + final int opcode, + final String owner, + final String name, + final String desc) + { + super(opcode); + this.owner = owner; + this.name = name; + this.desc = desc; + } + + /** + * Sets the opcode of this instruction. + * + * @param opcode the new instruction opcode. This opcode must be GETSTATIC, + * PUTSTATIC, GETFIELD or PUTFIELD. + */ + public void setOpcode(final int opcode) { + this.opcode = opcode; + } + + public void accept(final MethodVisitor cv) { + cv.visitFieldInsn(opcode, owner, name, desc); + } + + public int getType() { + return FIELD_INSN; + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/FieldNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/FieldNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/FieldNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,123 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; + +/** + * A node that represents a field. + * + * @author Eric Bruneton + */ +public class FieldNode extends MemberNode implements FieldVisitor { + + /** + * The field's access flags (see {@link org.objectweb.asm.Opcodes}). This + * field also indicates if the field is synthetic and/or deprecated. + */ + public int access; + + /** + * The field's name. + */ + public String name; + + /** + * The field's descriptor (see {@link org.objectweb.asm.Type}). + */ + public String desc; + + /** + * The field's signature. May be <tt>null</tt>. + */ + public String signature; + + /** + * The field's initial value. This field, which may be <tt>null</tt> if + * the field does not have an initial value, must be an {@link Integer}, a + * {@link Float}, a {@link Long}, a {@link Double} or a {@link String}. + */ + public Object value; + + /** + * Constructs a new {@link FieldNode}. + * + * @param access the field's access flags (see + * {@link org.objectweb.asm.Opcodes}). This parameter also indicates + * if the field is synthetic and/or deprecated. + * @param name the field's name. + * @param desc the field's descriptor (see {@link org.objectweb.asm.Type}). + * @param signature the field's signature. + * @param value the field's initial value. This parameter, which may be + * <tt>null</tt> if the field does not have an initial value, must + * be an {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double} or a {@link String}. + */ + public FieldNode( + final int access, + final String name, + final String desc, + final String signature, + final Object value) + { + this.access = access; + this.name = name; + this.desc = desc; + this.signature = signature; + this.value = value; + } + + /** + * Makes the given class visitor visit this field. + * + * @param cv a class visitor. + */ + public void accept(final ClassVisitor cv) { + FieldVisitor fv = cv.visitField(access, name, desc, signature, value); + int i, n; + n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); + for (i = 0; i < n; ++i) { + AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i); + an.accept(fv.visitAnnotation(an.desc, true)); + } + n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); + for (i = 0; i < n; ++i) { + AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i); + an.accept(fv.visitAnnotation(an.desc, false)); + } + n = attrs == null ? 0 : attrs.size(); + for (i = 0; i < n; ++i) { + fv.visitAttribute((Attribute) attrs.get(i)); + } + fv.visitEnd(); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/IincInsnNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/IincInsnNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/IincInsnNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,71 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +/** + * A node that represents an IINC instruction. + * + * @author Eric Bruneton + */ +public class IincInsnNode extends AbstractInsnNode { + + /** + * Index of the local variable to be incremented. + */ + public int var; + + /** + * Amount to increment the local variable by. + */ + public int incr; + + /** + * Constructs a new {@link IincInsnNode}. + * + * @param var index of the local variable to be incremented. + * @param incr increment amount to increment the local variable by. + */ + public IincInsnNode(final int var, final int incr) { + super(Opcodes.IINC); + this.var = var; + this.incr = incr; + } + + public void accept(final MethodVisitor mv) { + mv.visitIincInsn(var, incr); + } + + public int getType() { + return IINC_INSN; + } +} \ No newline at end of file Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/InnerClassNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/InnerClassNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/InnerClassNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,101 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.ClassVisitor; + +/** + * A node that represents an inner class. + * + * @author Eric Bruneton + */ +public class InnerClassNode { + + /** + * The internal name of an inner class (see + * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). + */ + public String name; + + /** + * The internal name of the class to which the inner class belongs (see + * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). May + * be <tt>null</tt>. + */ + public String outerName; + + /** + * The (simple) name of the inner class inside its enclosing class. May be + * <tt>null</tt> for anonymous inner classes. + */ + public String innerName; + + /** + * The access flags of the inner class as originally declared in the + * enclosing class. + */ + public int access; + + /** + * Constructs a new {@link InnerClassNode}. + * + * @param name the internal name of an inner class (see + * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). + * @param outerName the internal name of the class to which the inner class + * belongs (see + * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). + * May be <tt>null</tt>. + * @param innerName the (simple) name of the inner class inside its + * enclosing class. May be <tt>null</tt> for anonymous inner + * classes. + * @param access the access flags of the inner class as originally declared + * in the enclosing class. + */ + public InnerClassNode( + final String name, + final String outerName, + final String innerName, + final int access) + { + this.name = name; + this.outerName = outerName; + this.innerName = innerName; + this.access = access; + } + + /** + * Makes the given class visitor visit this inner class. + * + * @param cv a class visitor. + */ + public void accept(final ClassVisitor cv) { + cv.visitInnerClass(name, outerName, innerName, access); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/InsnNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/InsnNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/InsnNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,96 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.MethodVisitor; + +/** + * A node that represents a zero operand instruction. + * + * @author Eric Bruneton + */ +public class InsnNode extends AbstractInsnNode { + + private final static InsnNode[] INSNS; + + static { + INSNS = new InsnNode[255]; + for (int i = 0; i < INSNS.length; ++i) { + INSNS[i] = new InsnNode(i); + } + } + + /** + * Returns the {@link InsnNode} corresponding to the given opcode. + * + * @deprecated uses the constructor instead. + * + * @param opcode an instruction opcode. + * @return the {@link InsnNode} corresponding to the given opcode. + */ + public final static InsnNode getByOpcode(final int opcode) { + return INSNS[opcode]; + } + + /** + * Constructs a new {@link InsnNode}. + * + * @param opcode the opcode of the instruction to be constructed. This + * opcode must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, + * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, + * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, + * FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, + * FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, + * DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, + * FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, + * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, + * ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, + * LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, + * I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, + * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, + * MONITORENTER, or MONITOREXIT. + */ + public InsnNode(final int opcode) { + super(opcode); + } + + /** + * Makes the given visitor visit this instruction. + * + * @param mv a method visitor. + */ + public void accept(final MethodVisitor mv) { + mv.visitInsn(opcode); + } + + public int getType() { + return INSN; + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/IntInsnNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/IntInsnNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/IntInsnNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,75 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.MethodVisitor; + +/** + * A node that represents an instruction with a single int operand. + * + * @author Eric Bruneton + */ +public class IntInsnNode extends AbstractInsnNode { + + /** + * The operand of this instruction. + */ + public int operand; + + /** + * Constructs a new {@link IntInsnNode}. + * + * @param opcode the opcode of the instruction to be constructed. This + * opcode must be BIPUSH, SIPUSH or NEWARRAY. + * @param operand the operand of the instruction to be constructed. + */ + public IntInsnNode(final int opcode, final int operand) { + super(opcode); + this.operand = operand; + } + + /** + * Sets the opcode of this instruction. + * + * @param opcode the new instruction opcode. This opcode must be BIPUSH, + * SIPUSH or NEWARRAY. + */ + public void setOpcode(final int opcode) { + this.opcode = opcode; + } + + public void accept(final MethodVisitor mv) { + mv.visitIntInsn(opcode, operand); + } + + public int getType() { + return INT_INSN; + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/JumpInsnNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/JumpInsnNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/JumpInsnNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,84 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +/** + * A node that represents a jump instruction. A jump instruction is an + * instruction that may jump to another instruction. + * + * @author Eric Bruneton + */ +public class JumpInsnNode extends AbstractInsnNode { + + /** + * The operand of this instruction. This operand is a label that designates + * the instruction to which this instruction may jump. + */ + public Label label; + + /** + * Constructs a new {@link JumpInsnNode}. + * + * @param opcode the opcode of the type instruction to be constructed. This + * opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, + * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, + * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. + * @param label the operand of the instruction to be constructed. This + * operand is a label that designates the instruction to which the + * jump instruction may jump. + */ + public JumpInsnNode(final int opcode, final Label label) { + super(opcode); + this.label = label; + } + + /** + * Sets the opcode of this instruction. + * + * @param opcode the new instruction opcode. This opcode must be IFEQ, IFNE, + * IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, + * IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, + * IFNULL or IFNONNULL. + */ + public void setOpcode(final int opcode) { + this.opcode = opcode; + } + + public void accept(final MethodVisitor mv) { + mv.visitJumpInsn(opcode, label); + } + + public int getType() { + return JUMP_INSN; + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/LabelNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/LabelNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/LabelNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,54 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +/** + * An {@link AbstractInsnNode} that encapsulates a {@link Label}. + */ +public class LabelNode extends AbstractInsnNode { + + public Label label; + + public LabelNode(final Label label) { + super(-1); + this.label = label; + } + + public void accept(final MethodVisitor cv) { + cv.visitLabel(label); + } + + public int getType() { + return LABEL; + } +} \ No newline at end of file Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/LdcInsnNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/LdcInsnNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/LdcInsnNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,68 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +/** + * A node that represents an LDC instruction. + * + * @author Eric Bruneton + */ +public class LdcInsnNode extends AbstractInsnNode { + + /** + * The constant to be loaded on the stack. This parameter must be a non null + * {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a + * {@link String} or a {@link org.objectweb.asm.Type}. + */ + public Object cst; + + /** + * Constructs a new {@link LdcInsnNode}. + * + * @param cst the constant to be loaded on the stack. This parameter must be + * a non null {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double} or a {@link String}. + */ + public LdcInsnNode(final Object cst) { + super(Opcodes.LDC); + this.cst = cst; + } + + public void accept(final MethodVisitor mv) { + mv.visitLdcInsn(cst); + } + + public int getType() { + return LDC_INSN; + } +} \ No newline at end of file Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/LineNumberNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/LineNumberNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/LineNumberNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,73 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +/** + * A node that represents a line number declaration. + * + * @author Eric Bruneton + */ +public class LineNumberNode { + + /** + * A line number. This number refers to the source file from which the class + * was compiled. + */ + public int line; + + /** + * The first instruction corresponding to this line number. + */ + public Label start; + + /** + * Constructs a new {@link LineNumberNode}. + * + * @param line a line number. This number refers to the source file from + * which the class was compiled. + * @param start the first instruction corresponding to this line number. + */ + public LineNumberNode(final int line, final Label start) { + this.line = line; + this.start = start; + } + + /** + * Makes the given visitor visit this line number declaration. + * + * @param mv a method visitor. + */ + public void accept(final MethodVisitor mv) { + mv.visitLineNumber(line, start); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/LocalVariableNode.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/LocalVariableNode.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/LocalVariableNode.java 2007-01-07 13:53:11 UTC (rev 3033) @@ -0,0 +1,111 @@ +/*** + * ASM: a very small and fast Java bytecode manip... [truncated message content] |
From: <ls...@us...> - 2007-01-07 13:45:47
|
Revision: 3032 http://jnode.svn.sourceforge.net/jnode/?rev=3032&view=rev Author: lsantha Date: 2007-01-07 05:45:46 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Added Paths: ----------- trunk/core/src/classpath/org/org/objectweb/asm/tree/ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Analyzer.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/AnalyzerException.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicInterpreter.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicValue.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicVerifier.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowInterpreter.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowValue.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Frame.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/IntMap.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Interpreter.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/SimpleVerifier.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/SmallSet.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Subroutine.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Value.java trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/package.html Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Analyzer.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Analyzer.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Analyzer.java 2007-01-07 13:45:46 UTC (rev 3032) @@ -0,0 +1,416 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree.analysis; + +import java.util.ArrayList; +import java.util.List; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LookupSwitchInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; +import org.objectweb.asm.tree.TryCatchBlockNode; +import org.objectweb.asm.tree.VarInsnNode; + +/** + * A semantic bytecode analyzer. + * + * @author Eric Bruneton + */ +public class Analyzer implements Opcodes { + + private Interpreter interpreter; + + private int n; + + private IntMap indexes; + + private List[] handlers; + + private Frame[] frames; + + private Subroutine[] subroutines; + + private boolean[] queued; + + private int[] queue; + + private int top; + + private boolean jsr; + + /** + * Constructs a new {@link Analyzer}. + * + * @param interpreter the interpreter to be used to symbolically interpret + * the bytecode instructions. + */ + public Analyzer(final Interpreter interpreter) { + this.interpreter = interpreter; + } + + /** + * Analyzes the given method. + * + * @param owner the internal name of the class to which the method belongs. + * @param m the method to be analyzed. + * @return the symbolic state of the execution stack frame at each bytecode + * instruction of the method. The size of the returned array is + * equal to the number of instructions (and labels) of the method. A + * given frame is <tt>null</tt> if and only if the corresponding + * instruction cannot be reached (dead code). + * @throws AnalyzerException if a problem occurs during the analysis. + */ + public Frame[] analyze(final String owner, final MethodNode m) + throws AnalyzerException + { + n = m.instructions.size(); + indexes = new IntMap(2 * n); + handlers = new List[n]; + frames = new Frame[n]; + subroutines = new Subroutine[n]; + queued = new boolean[n]; + queue = new int[n]; + top = 0; + + // computes instruction indexes + for (int i = 0; i < n; ++i) { + Object insn = m.instructions.get(i); + if (insn instanceof LabelNode) { + insn = ((LabelNode) insn).label; + } + indexes.put(insn, i); + } + + // computes exception handlers for each instruction + for (int i = 0; i < m.tryCatchBlocks.size(); ++i) { + TryCatchBlockNode tcb = (TryCatchBlockNode) m.tryCatchBlocks.get(i); + int begin = indexes.get(tcb.start); + int end = indexes.get(tcb.end); + for (int j = begin; j < end; ++j) { + List insnHandlers = handlers[j]; + if (insnHandlers == null) { + insnHandlers = new ArrayList(); + handlers[j] = insnHandlers; + } + insnHandlers.add(tcb); + } + } + + // initializes the data structures for the control flow analysis + // algorithm + Frame current = newFrame(m.maxLocals, m.maxStack); + Frame handler = newFrame(m.maxLocals, m.maxStack); + Type[] args = Type.getArgumentTypes(m.desc); + int local = 0; + if ((m.access & ACC_STATIC) == 0) { + Type ctype = Type.getType("L" + owner + ";"); + current.setLocal(local++, interpreter.newValue(ctype)); + } + for (int i = 0; i < args.length; ++i) { + current.setLocal(local++, interpreter.newValue(args[i])); + if (args[i].getSize() == 2) { + current.setLocal(local++, interpreter.newValue(null)); + } + } + while (local < m.maxLocals) { + current.setLocal(local++, interpreter.newValue(null)); + } + merge(0, current, null); + + // control flow analysis + while (top > 0) { + int insn = queue[--top]; + Frame f = frames[insn]; + Subroutine subroutine = subroutines[insn]; + queued[insn] = false; + + try { + Object o = m.instructions.get(insn); + jsr = false; + + if (o instanceof LabelNode) { + merge(insn + 1, f, subroutine); + } else { + AbstractInsnNode insnNode = (AbstractInsnNode) o; + int insnOpcode = insnNode.getOpcode(); + + current.init(f).execute(insnNode, interpreter); + subroutine = subroutine == null ? null : subroutine.copy(); + + if (insnNode instanceof JumpInsnNode) { + JumpInsnNode j = (JumpInsnNode) insnNode; + if (insnOpcode != GOTO && insnOpcode != JSR) { + merge(insn + 1, current, subroutine); + } + if (insnOpcode == JSR) { + jsr = true; + merge(indexes.get(j.label), + current, + new Subroutine(j.label, m.maxLocals, j)); + } else { + merge(indexes.get(j.label), current, subroutine); + } + } else if (insnNode instanceof LookupSwitchInsnNode) { + LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode; + merge(indexes.get(lsi.dflt), current, subroutine); + for (int j = 0; j < lsi.labels.size(); ++j) { + Label label = (Label) lsi.labels.get(j); + merge(indexes.get(label), current, subroutine); + } + } else if (insnNode instanceof TableSwitchInsnNode) { + TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode; + merge(indexes.get(tsi.dflt), current, subroutine); + for (int j = 0; j < tsi.labels.size(); ++j) { + Label label = (Label) tsi.labels.get(j); + merge(indexes.get(label), current, subroutine); + } + } else if (insnOpcode == RET) { + if (subroutine == null) { + throw new AnalyzerException("RET instruction outside of a sub routine"); + } + for (int i = 0; i < subroutine.callers.size(); ++i) { + int caller = indexes.get(subroutine.callers.get(i)); + merge(caller + 1, + frames[caller], + current, + subroutines[caller], + subroutine.access); + } + } else if (insnOpcode != ATHROW + && (insnOpcode < IRETURN || insnOpcode > RETURN)) + { + if (subroutine != null) { + if (insnNode instanceof VarInsnNode) { + int var = ((VarInsnNode) insnNode).var; + subroutine.access[var] = true; + if (insnOpcode == LLOAD || insnOpcode == DLOAD + || insnOpcode == LSTORE + || insnOpcode == DSTORE) + { + subroutine.access[var + 1] = true; + } + } else if (insnNode instanceof IincInsnNode) { + int var = ((IincInsnNode) insnNode).var; + subroutine.access[var] = true; + } + } + merge(insn + 1, current, subroutine); + } + } + + List insnHandlers = handlers[insn]; + if (insnHandlers != null) { + for (int i = 0; i < insnHandlers.size(); ++i) { + TryCatchBlockNode tcb = (TryCatchBlockNode) insnHandlers.get(i); + Type type; + if (tcb.type == null) { + type = Type.getType("Ljava/lang/Throwable;"); + } else { + type = Type.getType("L" + tcb.type + ";"); + } + handler.init(f); + handler.clearStack(); + handler.push(interpreter.newValue(type)); + merge(indexes.get(tcb.handler), handler, subroutine); + } + } + } catch (AnalyzerException e) { + throw new AnalyzerException("Error at instruction " + insn + + ": " + e.getMessage(), e); + } catch(Exception e) { + throw new AnalyzerException("Error at instruction " + insn + + ": " + e.getMessage(), e); + } + } + + return frames; + } + + /** + * Returns the symbolic stack frame for each instruction of the last + * recently analyzed method. + * + * @return the symbolic state of the execution stack frame at each bytecode + * instruction of the method. The size of the returned array is + * equal to the number of instructions (and labels) of the method. A + * given frame is <tt>null</tt> if the corresponding instruction + * cannot be reached, or if an error occured during the analysis of + * the method. + */ + public Frame[] getFrames() { + return frames; + } + + /** + * Returns the index of the given instruction. + * + * @param insn a {@link Label} or {@link AbstractInsnNode} of the last + * recently analyzed method. + * @return the index of the given instruction of the last recently analyzed + * method. + */ + public int getIndex(final Object insn) { + return indexes.get(insn); + } + + /** + * Returns the exception handlers for the given instruction. + * + * @param insn the index of an instruction of the last recently analyzed + * method. + * @return a list of {@link TryCatchBlockNode} objects. + */ + public List getHandlers(final int insn) { + return handlers[insn]; + } + + /** + * Constructs a new frame with the given size. + * + * @param nLocals the maximum number of local variables of the frame. + * @param nStack the maximum stack size of the frame. + * @return the created frame. + */ + protected Frame newFrame(final int nLocals, final int nStack) { + return new Frame(nLocals, nStack); + } + + /** + * Constructs a new frame that is identical to the given frame. + * + * @param src a frame. + * @return the created frame. + */ + protected Frame newFrame(final Frame src) { + return new Frame(src); + } + + /** + * Creates a control flow graph edge. The default implementation of this + * method does nothing. It can be overriden in order to construct the + * control flow graph of a method (this method is called by the + * {@link #analyze analyze} method during its visit of the method's code). + * + * @param frame the frame corresponding to an instruction. + * @param successor the frame corresponding to a successor instruction. + */ + protected void newControlFlowEdge(final Frame frame, final Frame successor) + { + } + + // ------------------------------------------------------------------------- + + private void merge( + final int insn, + final Frame frame, + final Subroutine subroutine) throws AnalyzerException + { + if (insn > n - 1) { + throw new AnalyzerException("Execution can fall off end of the code"); + } + + Frame oldFrame = frames[insn]; + Subroutine oldSubroutine = subroutines[insn]; + boolean changes = false; + + if (oldFrame == null) { + frames[insn] = newFrame(frame); + changes = true; + } else { + changes |= oldFrame.merge(frame, interpreter); + } + + newControlFlowEdge(frame, oldFrame); + + if (oldSubroutine == null) { + if (subroutine != null) { + subroutines[insn] = subroutine.copy(); + changes = true; + } + } else { + if (subroutine != null) { + changes |= oldSubroutine.merge(subroutine, !jsr); + } + } + if (changes && !queued[insn]) { + queued[insn] = true; + queue[top++] = insn; + } + } + + private void merge( + final int insn, + final Frame beforeJSR, + final Frame afterRET, + final Subroutine subroutineBeforeJSR, + final boolean[] access) throws AnalyzerException + { + if (insn > n - 1) { + throw new AnalyzerException("Execution can fall off end of the code"); + } + + Frame oldFrame = frames[insn]; + Subroutine oldSubroutine = subroutines[insn]; + boolean changes = false; + + afterRET.merge(beforeJSR, access); + + if (oldFrame == null) { + frames[insn] = newFrame(afterRET); + changes = true; + } else { + changes |= oldFrame.merge(afterRET, access); + } + + newControlFlowEdge(afterRET, oldFrame); + + if (oldSubroutine == null) { + if (subroutineBeforeJSR != null) { + subroutines[insn] = subroutineBeforeJSR.copy(); + changes = true; + } + } else { + if (subroutineBeforeJSR != null) { + changes |= oldSubroutine.merge(subroutineBeforeJSR, !jsr); + } + } + if (changes && !queued[insn]) { + queued[insn] = true; + queue[top++] = insn; + } + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/AnalyzerException.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/AnalyzerException.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/AnalyzerException.java 2007-01-07 13:45:46 UTC (rev 3032) @@ -0,0 +1,56 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree.analysis; + +/** + * Thrown if a problem occurs during the analysis of a method. + * + * @author Bing Ran + * @author Eric Bruneton + */ +public class AnalyzerException extends Exception { + + public AnalyzerException(final String msg) { + super(msg); + } + + public AnalyzerException(final String msg, final Throwable exception) { + super(msg, exception); + } + + public AnalyzerException( + final String msg, + final Object expected, + final Value encountered) + { + super((msg == null ? "Expected " : msg + ": expected ") + expected + + ", but found " + encountered); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicInterpreter.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicInterpreter.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicInterpreter.java 2007-01-07 13:45:46 UTC (rev 3032) @@ -0,0 +1,335 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree.analysis; + +import java.util.List; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.IntInsnNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MultiANewArrayInsnNode; +import org.objectweb.asm.tree.TypeInsnNode; + +/** + * An {@link Interpreter} for {@link BasicValue} values. + * + * @author Eric Bruneton + * @author Bing Ran + */ +public class BasicInterpreter implements Opcodes, Interpreter { + + public Value newValue(final Type type) { + if (type == null) { + return BasicValue.UNINITIALIZED_VALUE; + } + switch (type.getSort()) { + case Type.VOID: + return null; + case Type.BOOLEAN: + case Type.CHAR: + case Type.BYTE: + case Type.SHORT: + case Type.INT: + return BasicValue.INT_VALUE; + case Type.FLOAT: + return BasicValue.FLOAT_VALUE; + case Type.LONG: + return BasicValue.LONG_VALUE; + case Type.DOUBLE: + return BasicValue.DOUBLE_VALUE; + case Type.ARRAY: + case Type.OBJECT: + return BasicValue.REFERENCE_VALUE; + default: + throw new RuntimeException("Internal error."); + } + } + + public Value newOperation(final AbstractInsnNode insn) { + switch (insn.getOpcode()) { + case ACONST_NULL: + return newValue(Type.getType("Lnull;")); + case ICONST_M1: + case ICONST_0: + case ICONST_1: + case ICONST_2: + case ICONST_3: + case ICONST_4: + case ICONST_5: + return BasicValue.INT_VALUE; + case LCONST_0: + case LCONST_1: + return BasicValue.LONG_VALUE; + case FCONST_0: + case FCONST_1: + case FCONST_2: + return BasicValue.FLOAT_VALUE; + case DCONST_0: + case DCONST_1: + return BasicValue.DOUBLE_VALUE; + case BIPUSH: + case SIPUSH: + return BasicValue.INT_VALUE; + case LDC: + Object cst = ((LdcInsnNode) insn).cst; + if (cst instanceof Integer) { + return BasicValue.INT_VALUE; + } else if (cst instanceof Float) { + return BasicValue.FLOAT_VALUE; + } else if (cst instanceof Long) { + return BasicValue.LONG_VALUE; + } else if (cst instanceof Double) { + return BasicValue.DOUBLE_VALUE; + } else if (cst instanceof Type) { + return newValue(Type.getType("Ljava/lang/Class;")); + } else { + return newValue(Type.getType(cst.getClass())); + } + case JSR: + return BasicValue.RETURNADDRESS_VALUE; + case GETSTATIC: + return newValue(Type.getType(((FieldInsnNode) insn).desc)); + case NEW: + return newValue(Type.getType("L" + ((TypeInsnNode) insn).desc + + ";")); + default: + throw new RuntimeException("Internal error."); + } + } + + public Value copyOperation(final AbstractInsnNode insn, final Value value) + throws AnalyzerException + { + return value; + } + + public Value unaryOperation(final AbstractInsnNode insn, final Value value) + throws AnalyzerException + { + switch (insn.getOpcode()) { + case INEG: + case IINC: + case L2I: + case F2I: + case D2I: + case I2B: + case I2C: + case I2S: + return BasicValue.INT_VALUE; + case FNEG: + case I2F: + case L2F: + case D2F: + return BasicValue.FLOAT_VALUE; + case LNEG: + case I2L: + case F2L: + case D2L: + return BasicValue.LONG_VALUE; + case DNEG: + case I2D: + case L2D: + case F2D: + return BasicValue.DOUBLE_VALUE; + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case TABLESWITCH: + case LOOKUPSWITCH: + case IRETURN: + case LRETURN: + case FRETURN: + case DRETURN: + case ARETURN: + case PUTSTATIC: + return null; + case GETFIELD: + return newValue(Type.getType(((FieldInsnNode) insn).desc)); + case NEWARRAY: + switch (((IntInsnNode) insn).operand) { + case T_BOOLEAN: + return newValue(Type.getType("[Z")); + case T_CHAR: + return newValue(Type.getType("[C")); + case T_BYTE: + return newValue(Type.getType("[B")); + case T_SHORT: + return newValue(Type.getType("[S")); + case T_INT: + return newValue(Type.getType("[I")); + case T_FLOAT: + return newValue(Type.getType("[F")); + case T_DOUBLE: + return newValue(Type.getType("[D")); + case T_LONG: + return newValue(Type.getType("[J")); + default: + throw new AnalyzerException("Invalid array type"); + } + case ANEWARRAY: + String desc = ((TypeInsnNode) insn).desc; + if (desc.charAt(0) == '[') { + return newValue(Type.getType("[" + desc)); + } else { + return newValue(Type.getType("[L" + desc + ";")); + } + case ARRAYLENGTH: + return BasicValue.INT_VALUE; + case ATHROW: + return null; + case CHECKCAST: + desc = ((TypeInsnNode) insn).desc; + if (desc.charAt(0) == '[') { + return newValue(Type.getType(desc)); + } else { + return newValue(Type.getType("L" + desc + ";")); + } + case INSTANCEOF: + return BasicValue.INT_VALUE; + case MONITORENTER: + case MONITOREXIT: + case IFNULL: + case IFNONNULL: + return null; + default: + throw new RuntimeException("Internal error."); + } + } + + public Value binaryOperation( + final AbstractInsnNode insn, + final Value value1, + final Value value2) throws AnalyzerException + { + switch (insn.getOpcode()) { + case IALOAD: + case BALOAD: + case CALOAD: + case SALOAD: + case IADD: + case ISUB: + case IMUL: + case IDIV: + case IREM: + case ISHL: + case ISHR: + case IUSHR: + case IAND: + case IOR: + case IXOR: + return BasicValue.INT_VALUE; + case FALOAD: + case FADD: + case FSUB: + case FMUL: + case FDIV: + case FREM: + return BasicValue.FLOAT_VALUE; + case LALOAD: + case LADD: + case LSUB: + case LMUL: + case LDIV: + case LREM: + case LSHL: + case LSHR: + case LUSHR: + case LAND: + case LOR: + case LXOR: + return BasicValue.LONG_VALUE; + case DALOAD: + case DADD: + case DSUB: + case DMUL: + case DDIV: + case DREM: + return BasicValue.DOUBLE_VALUE; + case AALOAD: + Type t = ((BasicValue) value1).getType(); + if (t != null && t.getSort() == Type.ARRAY) { + return newValue(t.getElementType()); + } else { + return BasicValue.REFERENCE_VALUE; + } + case LCMP: + case FCMPL: + case FCMPG: + case DCMPL: + case DCMPG: + return BasicValue.INT_VALUE; + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + case IF_ACMPEQ: + case IF_ACMPNE: + case PUTFIELD: + return null; + default: + throw new RuntimeException("Internal error."); + } + } + + public Value ternaryOperation( + final AbstractInsnNode insn, + final Value value1, + final Value value2, + final Value value3) throws AnalyzerException + { + return null; + } + + public Value naryOperation(final AbstractInsnNode insn, final List values) + throws AnalyzerException + { + if (insn.getOpcode() == MULTIANEWARRAY) { + return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); + } else { + return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); + } + } + + public Value merge(final Value v, final Value w) { + if (!v.equals(w)) { + return BasicValue.UNINITIALIZED_VALUE; + } + return v; + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicValue.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicValue.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicValue.java 2007-01-07 13:45:46 UTC (rev 3032) @@ -0,0 +1,105 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree.analysis; + +import org.objectweb.asm.Type; + +/** + * A {@link Value} that is represented by its type in a seven types type sytem. + * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE, + * REFERENCE and RETURNADDRESS types. + * + * @author Eric Bruneton + */ +public class BasicValue implements Value { + + public final static Value UNINITIALIZED_VALUE = new BasicValue(null); + + public final static Value INT_VALUE = new BasicValue(Type.INT_TYPE); + + public final static Value FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE); + + public final static Value LONG_VALUE = new BasicValue(Type.LONG_TYPE); + + public final static Value DOUBLE_VALUE = new BasicValue(Type.DOUBLE_TYPE); + + public final static Value REFERENCE_VALUE = new BasicValue(Type.getType("Ljava/lang/Object;")); + + public final static Value RETURNADDRESS_VALUE = new BasicValue(null); + + private Type type; + + public BasicValue(final Type type) { + this.type = type; + } + + public Type getType() { + return type; + } + + public int getSize() { + return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1; + } + + public boolean isReference() { + return type != null + && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY); + } + + public boolean equals(final Object value) { + if (value == this) { + return true; + } else if (value instanceof BasicValue) { + if (type == null) { + return ((BasicValue) value).type == null; + } else { + return type.equals(((BasicValue) value).type); + } + } else { + return false; + } + } + + public int hashCode() { + return type == null ? 0 : type.hashCode(); + } + + public String toString() { + if (this == UNINITIALIZED_VALUE) { + return "."; + } else if (this == RETURNADDRESS_VALUE) { + return "A"; + } else if (this == REFERENCE_VALUE) { + return "R"; + } else { + return type.getDescriptor(); + } + } +} \ No newline at end of file Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicVerifier.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicVerifier.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicVerifier.java 2007-01-07 13:45:46 UTC (rev 3032) @@ -0,0 +1,428 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree.analysis; + +import java.util.List; + +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; + +/** + * An extended {@link BasicInterpreter} that checks that bytecode instructions + * are correctly used. + * + * @author Eric Bruneton + * @author Bing Ran + */ +public class BasicVerifier extends BasicInterpreter { + + public Value copyOperation(final AbstractInsnNode insn, final Value value) + throws AnalyzerException + { + Value expected; + switch (insn.getOpcode()) { + case ILOAD: + case ISTORE: + expected = BasicValue.INT_VALUE; + break; + case FLOAD: + case FSTORE: + expected = BasicValue.FLOAT_VALUE; + break; + case LLOAD: + case LSTORE: + expected = BasicValue.LONG_VALUE; + break; + case DLOAD: + case DSTORE: + expected = BasicValue.DOUBLE_VALUE; + break; + case ALOAD: + if (!((BasicValue) value).isReference()) { + throw new AnalyzerException(null, + "an object reference", + value); + } + return value; + case ASTORE: + if (!((BasicValue) value).isReference() + && value != BasicValue.RETURNADDRESS_VALUE) + { + throw new AnalyzerException(null, + "an object reference or a return address", + value); + } + return value; + default: + return value; + } + // type is necessarily a primitive type here, + // so value must be == to expected value + if (value != expected) { + throw new AnalyzerException(null, expected, value); + } + return value; + } + + public Value unaryOperation(final AbstractInsnNode insn, Value value) + throws AnalyzerException + { + Value expected; + switch (insn.getOpcode()) { + case INEG: + case IINC: + case I2F: + case I2L: + case I2D: + case I2B: + case I2C: + case I2S: + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case TABLESWITCH: + case LOOKUPSWITCH: + case IRETURN: + case NEWARRAY: + case ANEWARRAY: + expected = BasicValue.INT_VALUE; + break; + case FNEG: + case F2I: + case F2L: + case F2D: + case FRETURN: + expected = BasicValue.FLOAT_VALUE; + break; + case LNEG: + case L2I: + case L2F: + case L2D: + case LRETURN: + expected = BasicValue.LONG_VALUE; + break; + case DNEG: + case D2I: + case D2F: + case D2L: + case DRETURN: + expected = BasicValue.DOUBLE_VALUE; + break; + case GETFIELD: + expected = newValue(Type.getType("L" + + ((FieldInsnNode) insn).owner + ";")); + break; + case CHECKCAST: + if (!((BasicValue) value).isReference()) { + throw new AnalyzerException(null, + "an object reference", + value); + } + return super.unaryOperation(insn, value); + case ARRAYLENGTH: + if (!isArrayValue(value)) { + throw new AnalyzerException(null, + "an array reference", + value); + } + return super.unaryOperation(insn, value); + case ARETURN: + case ATHROW: + case INSTANCEOF: + case MONITORENTER: + case MONITOREXIT: + case IFNULL: + case IFNONNULL: + if (!((BasicValue) value).isReference()) { + throw new AnalyzerException(null, + "an object reference", + value); + } + return super.unaryOperation(insn, value); + case PUTSTATIC: + expected = newValue(Type.getType(((FieldInsnNode) insn).desc)); + break; + default: + throw new RuntimeException("Internal error."); + } + if (!isSubTypeOf(value, expected)) { + throw new AnalyzerException(null, expected, value); + } + return super.unaryOperation(insn, value); + } + + public Value binaryOperation( + final AbstractInsnNode insn, + final Value value1, + final Value value2) throws AnalyzerException + { + Value expected1; + Value expected2; + switch (insn.getOpcode()) { + case IALOAD: + expected1 = newValue(Type.getType("[I")); + expected2 = BasicValue.INT_VALUE; + break; + case BALOAD: + if (!isSubTypeOf(value1, newValue(Type.getType("[Z")))) { + expected1 = newValue(Type.getType("[B")); + } else { + expected1 = newValue(Type.getType("[Z")); + } + expected2 = BasicValue.INT_VALUE; + break; + case CALOAD: + expected1 = newValue(Type.getType("[C")); + expected2 = BasicValue.INT_VALUE; + break; + case SALOAD: + expected1 = newValue(Type.getType("[S")); + expected2 = BasicValue.INT_VALUE; + break; + case LALOAD: + expected1 = newValue(Type.getType("[J")); + expected2 = BasicValue.INT_VALUE; + break; + case FALOAD: + expected1 = newValue(Type.getType("[F")); + expected2 = BasicValue.INT_VALUE; + break; + case DALOAD: + expected1 = newValue(Type.getType("[D")); + expected2 = BasicValue.INT_VALUE; + break; + case AALOAD: + expected1 = newValue(Type.getType("[Ljava/lang/Object;")); + expected2 = BasicValue.INT_VALUE; + break; + case IADD: + case ISUB: + case IMUL: + case IDIV: + case IREM: + case ISHL: + case ISHR: + case IUSHR: + case IAND: + case IOR: + case IXOR: + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + expected1 = BasicValue.INT_VALUE; + expected2 = BasicValue.INT_VALUE; + break; + case FADD: + case FSUB: + case FMUL: + case FDIV: + case FREM: + case FCMPL: + case FCMPG: + expected1 = BasicValue.FLOAT_VALUE; + expected2 = BasicValue.FLOAT_VALUE; + break; + case LADD: + case LSUB: + case LMUL: + case LDIV: + case LREM: + case LAND: + case LOR: + case LXOR: + case LCMP: + expected1 = BasicValue.LONG_VALUE; + expected2 = BasicValue.LONG_VALUE; + break; + case LSHL: + case LSHR: + case LUSHR: + expected1 = BasicValue.LONG_VALUE; + expected2 = BasicValue.INT_VALUE; + break; + case DADD: + case DSUB: + case DMUL: + case DDIV: + case DREM: + case DCMPL: + case DCMPG: + expected1 = BasicValue.DOUBLE_VALUE; + expected2 = BasicValue.DOUBLE_VALUE; + break; + case IF_ACMPEQ: + case IF_ACMPNE: + expected1 = BasicValue.REFERENCE_VALUE; + expected2 = BasicValue.REFERENCE_VALUE; + break; + case PUTFIELD: + FieldInsnNode fin = (FieldInsnNode) insn; + expected1 = newValue(Type.getType("L" + fin.owner + ";")); + expected2 = newValue(Type.getType(fin.desc)); + break; + default: + throw new RuntimeException("Internal error."); + } + if (!isSubTypeOf(value1, expected1)) { + throw new AnalyzerException("First argument", expected1, value1); + } else if (!isSubTypeOf(value2, expected2)) { + throw new AnalyzerException("Second argument", expected2, value2); + } + if (insn.getOpcode() == AALOAD) { + return getElementValue(value1); + } else { + return super.binaryOperation(insn, value1, value2); + } + } + + public Value ternaryOperation( + final AbstractInsnNode insn, + final Value value1, + final Value value2, + final Value value3) throws AnalyzerException + { + Value expected1; + Value expected3; + switch (insn.getOpcode()) { + case IASTORE: + expected1 = newValue(Type.getType("[I")); + expected3 = BasicValue.INT_VALUE; + break; + case BASTORE: + if (!isSubTypeOf(value1, newValue(Type.getType("[Z")))) { + expected1 = newValue(Type.getType("[B")); + } else { + expected1 = newValue(Type.getType("[Z")); + } + expected3 = BasicValue.INT_VALUE; + break; + case CASTORE: + expected1 = newValue(Type.getType("[C")); + expected3 = BasicValue.INT_VALUE; + break; + case SASTORE: + expected1 = newValue(Type.getType("[S")); + expected3 = BasicValue.INT_VALUE; + break; + case LASTORE: + expected1 = newValue(Type.getType("[J")); + expected3 = BasicValue.LONG_VALUE; + break; + case FASTORE: + expected1 = newValue(Type.getType("[F")); + expected3 = BasicValue.FLOAT_VALUE; + break; + case DASTORE: + expected1 = newValue(Type.getType("[D")); + expected3 = BasicValue.DOUBLE_VALUE; + break; + case AASTORE: + expected1 = value1; + expected3 = BasicValue.REFERENCE_VALUE; + break; + default: + throw new RuntimeException("Internal error."); + } + if (!isSubTypeOf(value1, expected1)) { + throw new AnalyzerException("First argument", "a " + expected1 + + " array reference", value1); + } else if (value2 != BasicValue.INT_VALUE) { + throw new AnalyzerException("Second argument", + BasicValue.INT_VALUE, + value2); + } else if (!isSubTypeOf(value3, expected3)) { + throw new AnalyzerException("Third argument", expected3, value3); + } + return null; + } + + public Value naryOperation(final AbstractInsnNode insn, final List values) + throws AnalyzerException + { + int opcode = insn.getOpcode(); + if (opcode == MULTIANEWARRAY) { + for (int i = 0; i < values.size(); ++i) { + if (values.get(i) != BasicValue.INT_VALUE) { + throw new AnalyzerException(null, + BasicValue.INT_VALUE, + (Value) values.get(i)); + } + } + } else { + int i = 0; + int j = 0; + if (opcode != INVOKESTATIC) { + String own = ((MethodInsnNode) insn).owner; + if (own.charAt(0) != '[') { // can happen with JDK1.5 clone() + own = "L" + own + ";"; + } + Type owner = Type.getType(own); + if (!isSubTypeOf((Value) values.get(i++), newValue(owner))) { + throw new AnalyzerException("Method owner", + newValue(owner), + (Value) values.get(0)); + } + } + Type[] args = Type.getArgumentTypes(((MethodInsnNode) insn).desc); + while (i < values.size()) { + Value expected = newValue(args[j++]); + Value encountered = (Value) values.get(i++); + if (!isSubTypeOf(encountered, expected)) { + throw new AnalyzerException("Argument " + j, + expected, + encountered); + } + } + } + return super.naryOperation(insn, values); + } + + protected boolean isArrayValue(final Value value) { + return ((BasicValue) value).isReference(); + } + + protected Value getElementValue(final Value objectArrayValue) + throws AnalyzerException + { + return BasicValue.REFERENCE_VALUE; + } + + protected boolean isSubTypeOf(final Value value, final Value expected) { + return value == expected; + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowInterpreter.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowInterpreter.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowInterpreter.java 2007-01-07 13:45:46 UTC (rev 3032) @@ -0,0 +1,174 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.tree.analysis; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; + +/** + * An {@link Interpreter} for {@link DataflowValue} values. + * + * @author Eric Bruneton + */ +public class DataflowInterpreter implements Opcodes, Interpreter { + + public Value newValue(final Type type) { + return new DataflowValue(type == null ? 1 : type.getSize()); + } + + public Value newOperation(final AbstractInsnNode insn) { + int size; + switch (insn.getOpcode()) { + case LCONST_0: + case LCONST_1: + case DCONST_0: + case DCONST_1: + size = 2; + break; + case LDC: + Object cst = ((LdcInsnNode) insn).cst; + size = cst instanceof Long || cst instanceof Double ? 2 : 1; + break; + case GETSTATIC: + size = Type.getType(((FieldInsnNode) insn).desc).getSize(); + break; + default: + size = 1; + } + return new DataflowValue(size, insn); + } + + public Value copyOperation(final AbstractInsnNode insn, final Value value) { + return new DataflowValue(value.getSize(), insn); + } + + public Value unaryOperation(final AbstractInsnNode insn, final Value value) + { + int size; + switch (insn.getOpcode()) { + case LNEG: + case DNEG: + case I2L: + case I2D: + case L2D: + case F2L: + case F2D: + case D2L: + size = 2; + break; + case GETFIELD: + size = Type.getType(((FieldInsnNode) insn).desc).getSize(); + break; + default: + size = 1; + } + return new DataflowValue(size, insn); + } + + public Value binaryOperation( + final AbstractInsnNode insn, + final Value value1, + final Value value2) + { + int size; + switch (insn.getOpcode()) { + case LALOAD: + case DALOAD: + case LADD: + case DADD: + case LSUB: + case DSUB: + case LMUL: + case DMUL: + case LDIV: + case DDIV: + case LREM: + case DREM: + case LSHL: + case LSHR: + case LUSHR: + case LAND: + case LOR: + case LXOR: + size = 2; + break; + default: + size = 1; + } + return new DataflowValue(size, insn); + } + + public Value ternaryOperation( + final AbstractInsnNode insn, + final Value value1, + final Value value2, + final Value value3) + { + return new DataflowValue(1, insn); + } + + public Value naryOperation(final AbstractInsnNode insn, final List values) { + int size; + if (insn.getOpcode() == MULTIANEWARRAY) { + size = 1; + } else { + size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize(); + } + return new DataflowValue(size, insn); + } + + public Value merge(final Value v, final Value w) { + DataflowValue dv = (DataflowValue) v; + DataflowValue dw = (DataflowValue) w; + if (dv.insns instanceof SmallSet && dw.insns instanceof SmallSet) { + Set s = ((SmallSet) dv.insns).union((SmallSet) dw.insns); + if (s == dv.insns && dv.size == dw.size) { + return v; + } else { + return new DataflowValue(Math.min(dv.size, dw.size), s); + } + } + if (dv.size != dw.size || !dv.insns.containsAll(dw.insns)) { + Set s = new HashSet(); + s.addAll(dv.insns); + s.addAll(dw.insns); + return new DataflowValue(Math.min(dv.size, dw.size), s); + } + return v; + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowValue.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowValue.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowValue.java 2007-01-07 13:45:46 UTC (rev 3032) @@ -0,0 +1,92 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * ... [truncated message content] |
From: <ls...@us...> - 2007-01-07 13:44:40
|
Revision: 3031 http://jnode.svn.sourceforge.net/jnode/?rev=3031&view=rev Author: lsantha Date: 2007-01-07 05:44:38 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Added Paths: ----------- trunk/core/src/classpath/org/org/objectweb/asm/signature/ trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureReader.java trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureWriter.java trunk/core/src/classpath/org/org/objectweb/asm/signature/package.html Added: trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureReader.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureReader.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureReader.java 2007-01-07 13:44:38 UTC (rev 3031) @@ -0,0 +1,233 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.signature; + +/** + * A type signature parser to make a signature visitor visit an existing + * signature. + * + * @author Thomas Hallgren + * @author Eric Bruneton + */ +public class SignatureReader { + + /** + * The signature to be read. + */ + private final String signature; + + /** + * Constructs a {@link SignatureReader} for the given signature. + * + * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, + * or <i>FieldTypeSignature</i>. + */ + public SignatureReader(final String signature) { + this.signature = signature; + } + + /** + * Makes the given visitor visit the signature of this + * {@link SignatureReader}. This signature is the one specified in the + * constructor (see {@link #SignatureReader(String) SignatureReader}). This + * method is intended to be called on a {@link SignatureReader} that was + * created using a <i>ClassSignature</i> (such as the + * <code>signature</code> parameter of the + * {@link org.objectweb.asm.ClassVisitor#visit ClassVisitor.visit} method) + * or a <i>MethodTypeSignature</i> (such as the <code>signature</code> + * parameter of the + * {@link org.objectweb.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod} + * method). + * + * @param v the visitor that must visit this signature. + */ + public void accept(final SignatureVisitor v) { + String signature = this.signature; + int len = signature.length(); + int pos; + char c; + + if (signature.charAt(0) == '<') { + pos = 2; + do { + int end = signature.indexOf(':', pos); + v.visitFormalTypeParameter(signature.substring(pos - 1, end)); + pos = end + 1; + + c = signature.charAt(pos); + if (c == 'L' || c == '[' || c == 'T') { + pos = parseType(signature, pos, v.visitClassBound()); + } + + for (;;) { + if ((c = signature.charAt(pos++)) == ':') { + pos = parseType(signature, pos, v.visitInterfaceBound()); + } else { + break; + } + } + } while (c != '>'); + } else { + pos = 0; + } + + if (signature.charAt(pos) == '(') { + pos = pos + 1; + while (signature.charAt(pos) != ')') { + pos = parseType(signature, pos, v.visitParameterType()); + } + pos = parseType(signature, pos + 1, v.visitReturnType()); + while (pos < len) { + pos = parseType(signature, pos + 1, v.visitExceptionType()); + } + } else { + pos = parseType(signature, pos, v.visitSuperclass()); + while (pos < len) { + pos = parseType(signature, pos, v.visitInterface()); + } + } + } + + /** + * Makes the given visitor visit the signature of this + * {@link SignatureReader}. This signature is the one specified in the + * constructor (see {@link #SignatureReader(String) SignatureReader}). This + * method is intended to be called on a {@link SignatureReader} that was + * created using a <i>FieldTypeSignature</i>, such as the + * <code>signature</code> parameter of the + * {@link org.objectweb.asm.ClassVisitor#visitField + * ClassVisitor.visitField} or {@link + * org.objectweb.asm.MethodVisitor#visitLocalVariable + * MethodVisitor.visitLocalVariable} methods. + * + * @param v the visitor that must visit this signature. + */ + public void acceptType(final SignatureVisitor v) { + parseType(this.signature, 0, v); + } + + /** + * Parses a field type signature and makes the given visitor visit it. + * + * @param signature a string containing the signature that must be parsed. + * @param pos index of the first character of the signature to parsed. + * @param v the visitor that must visit this signature. + * @return the index of the first character after the parsed signature. + */ + private static int parseType( + final String signature, + int pos, + final SignatureVisitor v) + { + char c; + int start, end; + boolean visited, inner; + String name; + + switch (c = signature.charAt(pos++)) { + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + case 'F': + case 'J': + case 'D': + case 'V': + v.visitBaseType(c); + return pos; + + case '[': + return parseType(signature, pos, v.visitArrayType()); + + case 'T': + end = signature.indexOf(';', pos); + v.visitTypeVariable(signature.substring(pos, end)); + return end + 1; + + default: // case 'L': + start = pos; + visited = false; + inner = false; + for (;;) { + switch (c = signature.charAt(pos++)) { + case '.': + case ';': + if (!visited) { + name = signature.substring(start, pos - 1); + if (inner) { + v.visitInnerClassType(name); + } else { + v.visitClassType(name); + } + } + if (c == ';') { + v.visitEnd(); + return pos; + } + start = pos; + visited = false; + inner = true; + break; + + case '<': + name = signature.substring(start, pos - 1); + if (inner) { + v.visitInnerClassType(name); + } else { + v.visitClassType(name); + } + visited = true; + top: for (;;) { + switch (c = signature.charAt(pos)) { + case '>': + break top; + case '*': + ++pos; + v.visitTypeArgument(); + break; + case '+': + case '-': + pos = parseType(signature, + pos + 1, + v.visitTypeArgument(c)); + break; + default: + pos = parseType(signature, + pos, + v.visitTypeArgument('=')); + break; + } + } + } + } + } + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureVisitor.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureVisitor.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureVisitor.java 2007-01-07 13:44:38 UTC (rev 3031) @@ -0,0 +1,185 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.signature; + +/** + * A visitor to visit a generic signature. The methods of this interface must be + * called in one of the three following orders (the last one is the only valid + * order for a {@link SignatureVisitor} that is returned by a method of this + * interface): <ul> <li><i>ClassSignature</i> = ( + * <tt>visitFormalTypeParameter</tt> + * <tt>visitClassBound</tt>? + * <tt>visitInterfaceBound</tt>* )* ( <tt>visitSuperClass</tt> + * <tt>visitInterface</tt>* )</li> + * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt> + * <tt>visitClassBound</tt>? + * <tt>visitInterfaceBound</tt>* )* ( <tt>visitParameterType</tt>* + * <tt>visitReturnType</tt> + * <tt>visitExceptionType</tt>* )</li> <li><i>TypeSignature</i> = + * <tt>visitBaseType</tt> | <tt>visitTypeVariable</tt> | + * <tt>visitArrayType</tt> | ( + * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* ( + * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* + * <tt>visitEnd</tt> ) )</li> </ul> + * + * @author Thomas Hallgren + * @author Eric Bruneton + */ +public interface SignatureVisitor { + + /** + * Wildcard for an "extends" type argument. + */ + char EXTENDS = '+'; + + /** + * Wildcard for a "super" type argument. + */ + char SUPER = '-'; + + /** + * Wildcard for a normal type argument. + */ + char INSTANCEOF = '='; + + /** + * Visits a formal type parameter. + * + * @param name the name of the formal parameter. + */ + void visitFormalTypeParameter(String name); + + /** + * Visits the class bound of the last visited formal type parameter. + * + * @return a non null visitor to visit the signature of the class bound. + */ + SignatureVisitor visitClassBound(); + + /** + * Visits an interface bound of the last visited formal type parameter. + * + * @return a non null visitor to visit the signature of the interface bound. + */ + SignatureVisitor visitInterfaceBound(); + + /** + * Visits the type of the super class. + * + * @return a non null visitor to visit the signature of the super class + * type. + */ + SignatureVisitor visitSuperclass(); + + /** + * Visits the type of an interface implemented by the class. + * + * @return a non null visitor to visit the signature of the interface type. + */ + SignatureVisitor visitInterface(); + + /** + * Visits the type of a method parameter. + * + * @return a non null visitor to visit the signature of the parameter type. + */ + SignatureVisitor visitParameterType(); + + /** + * Visits the return type of the method. + * + * @return a non null visitor to visit the signature of the return type. + */ + SignatureVisitor visitReturnType(); + + /** + * Visits the type of a method exception. + * + * @return a non null visitor to visit the signature of the exception type. + */ + SignatureVisitor visitExceptionType(); + + /** + * Visits a signature corresponding to a primitive type. + * + * @param descriptor the descriptor of the primitive type, or 'V' for + * <tt>void</tt>. + */ + void visitBaseType(char descriptor); + + /** + * Visits a signature corresponding to a type variable. + * + * @param name the name of the type variable. + */ + void visitTypeVariable(String name); + + /** + * Visits a signature corresponding to an array type. + * + * @return a non null visitor to visit the signature of the array element + * type. + */ + SignatureVisitor visitArrayType(); + + /** + * Starts the visit of a signature corresponding to a class or interface + * type. + * + * @param name the internal name of the class or interface. + */ + void visitClassType(String name); + + /** + * Visits an inner class. + * + * @param name the local name of the inner class in its enclosing class. + */ + void visitInnerClassType(String name); + + /** + * Visits an unbounded type argument of the last visited class or inner + * class type. + */ + void visitTypeArgument(); + + /** + * Visits a type argument of the last visited class or inner class type. + * + * @param wildcard '+', '-' or '='. + * @return a non null visitor to visit the signature of the type argument. + */ + SignatureVisitor visitTypeArgument(char wildcard); + + /** + * Ends the visit of a signature corresponding to a class or interface type. + */ + void visitEnd(); +} Added: trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureWriter.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureWriter.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/signature/SignatureWriter.java 2007-01-07 13:44:38 UTC (rev 3031) @@ -0,0 +1,207 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.signature; + +/** + * A signature visitor that generates signatures in string format. + * + * @author Thomas Hallgren + * @author Eric Bruneton + */ +public class SignatureWriter implements SignatureVisitor { + + /** + * Buffer used to construct the signature. + */ + private final StringBuffer buf = new StringBuffer(); + + /** + * Indicates if the signature contains formal type parameters. + */ + private boolean hasFormals; + + /** + * Indicates if the signature contains method parameter types. + */ + private boolean hasParameters; + + /** + * Stack used to keep track of class types that have arguments. Each element + * of this stack is a boolean encoded in one bit. The top of the stack is + * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping = + * /2. + */ + private int argumentStack; + + /** + * Constructs a new {@link SignatureWriter} object. + */ + public SignatureWriter() { + } + + // ------------------------------------------------------------------------ + // Implementation of the SignatureVisitor interface + // ------------------------------------------------------------------------ + + public void visitFormalTypeParameter(String name) { + if (!hasFormals) { + hasFormals = true; + buf.append('<'); + } + buf.append(name); + buf.append(':'); + } + + public SignatureVisitor visitClassBound() { + return this; + } + + public SignatureVisitor visitInterfaceBound() { + buf.append(':'); + return this; + } + + public SignatureVisitor visitSuperclass() { + endFormals(); + return this; + } + + public SignatureVisitor visitInterface() { + return this; + } + + public SignatureVisitor visitParameterType() { + endFormals(); + if (!hasParameters) { + hasParameters = true; + buf.append('('); + } + return this; + } + + public SignatureVisitor visitReturnType() { + endFormals(); + if (!hasParameters) { + buf.append('('); + } + buf.append(')'); + return this; + } + + public SignatureVisitor visitExceptionType() { + buf.append('^'); + return this; + } + + public void visitBaseType(char descriptor) { + buf.append(descriptor); + } + + public void visitTypeVariable(String name) { + buf.append('T'); + buf.append(name); + buf.append(';'); + } + + public SignatureVisitor visitArrayType() { + buf.append('['); + return this; + } + + public void visitClassType(String name) { + buf.append('L'); + buf.append(name); + argumentStack *= 2; + } + + public void visitInnerClassType(String name) { + endArguments(); + buf.append('.'); + buf.append(name); + argumentStack *= 2; + } + + public void visitTypeArgument() { + if (argumentStack % 2 == 0) { + ++argumentStack; + buf.append('<'); + } + buf.append('*'); + } + + public SignatureVisitor visitTypeArgument(char wildcard) { + if (argumentStack % 2 == 0) { + ++argumentStack; + buf.append('<'); + } + if (wildcard != '=') { + buf.append(wildcard); + } + return this; + } + + public void visitEnd() { + endArguments(); + buf.append(';'); + } + + /** + * Returns the signature that was built by this signature writer. + * + * @return the signature that was built by this signature writer. + */ + public String toString() { + return buf.toString(); + } + + // ------------------------------------------------------------------------ + // Utility methods + // ------------------------------------------------------------------------ + + /** + * Ends the formal type parameters section of the signature. + */ + private void endFormals() { + if (hasFormals) { + hasFormals = false; + buf.append('>'); + } + } + + /** + * Ends the type arguments of a class or inner class type. + */ + private void endArguments() { + if (argumentStack % 2 == 1) { + buf.append('>'); + } + argumentStack /= 2; + } +} \ No newline at end of file Added: trunk/core/src/classpath/org/org/objectweb/asm/signature/package.html =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/signature/package.html (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/signature/package.html 2007-01-07 13:44:38 UTC (rev 3031) @@ -0,0 +1,36 @@ +<html> +<!-- + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. +--> +<body> +Provides support for type signatures. + +@since ASM 2.0 +</body> +</html> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-07 13:44:10
|
Revision: 3030 http://jnode.svn.sourceforge.net/jnode/?rev=3030&view=rev Author: lsantha Date: 2007-01-07 05:44:08 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Added Paths: ----------- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/AnnotationConstantsCollector.java trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ClassConstantsCollector.java trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ClassOptimizer.java trunk/core/src/classpath/org/org/objectweb/asm/optimizer/Constant.java trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ConstantPool.java trunk/core/src/classpath/org/org/objectweb/asm/optimizer/FieldConstantsCollector.java trunk/core/src/classpath/org/org/objectweb/asm/optimizer/JarOptimizer.java trunk/core/src/classpath/org/org/objectweb/asm/optimizer/MethodConstantsCollector.java trunk/core/src/classpath/org/org/objectweb/asm/optimizer/MethodOptimizer.java trunk/core/src/classpath/org/org/objectweb/asm/optimizer/NameMapping.java trunk/core/src/classpath/org/org/objectweb/asm/optimizer/Shrinker.java trunk/core/src/classpath/org/org/objectweb/asm/optimizer/shrink.properties Added: trunk/core/src/classpath/org/org/objectweb/asm/optimizer/AnnotationConstantsCollector.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/AnnotationConstantsCollector.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/AnnotationConstantsCollector.java 2007-01-07 13:44:08 UTC (rev 3030) @@ -0,0 +1,150 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.optimizer; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Type; + +/** + * An {@link AnnotationVisitor} that collects the {@link Constant}s of the + * annotations it visits. + * + * @author Eric Bruneton + */ +public class AnnotationConstantsCollector implements AnnotationVisitor { + + private AnnotationVisitor av; + + private ConstantPool cp; + + public AnnotationConstantsCollector( + final AnnotationVisitor av, + final ConstantPool cp) + { + this.av = av; + this.cp = cp; + } + + public void visit(final String name, final Object value) { + if (name != null) { + cp.newUTF8(name); + } + if (value instanceof Byte) { + cp.newInteger(((Byte) value).byteValue()); + } else if (value instanceof Boolean) { + cp.newInteger(((Boolean) value).booleanValue() ? 1 : 0); + } else if (value instanceof Character) { + cp.newInteger(((Character) value).charValue()); + } else if (value instanceof Short) { + cp.newInteger(((Short) value).shortValue()); + } else if (value instanceof Type) { + cp.newUTF8(((Type) value).getDescriptor()); + } else if (value instanceof byte[]) { + byte[] v = (byte[]) value; + for (int i = 0; i < v.length; i++) { + cp.newInteger(v[i]); + } + } else if (value instanceof boolean[]) { + boolean[] v = (boolean[]) value; + for (int i = 0; i < v.length; i++) { + cp.newInteger(v[i] ? 1 : 0); + } + } else if (value instanceof short[]) { + short[] v = (short[]) value; + for (int i = 0; i < v.length; i++) { + cp.newInteger(v[i]); + } + } else if (value instanceof char[]) { + char[] v = (char[]) value; + for (int i = 0; i < v.length; i++) { + cp.newInteger(v[i]); + } + } else if (value instanceof int[]) { + int[] v = (int[]) value; + for (int i = 0; i < v.length; i++) { + cp.newInteger(v[i]); + } + } else if (value instanceof long[]) { + long[] v = (long[]) value; + for (int i = 0; i < v.length; i++) { + cp.newLong(v[i]); + } + } else if (value instanceof float[]) { + float[] v = (float[]) value; + for (int i = 0; i < v.length; i++) { + cp.newFloat(v[i]); + } + } else if (value instanceof double[]) { + double[] v = (double[]) value; + for (int i = 0; i < v.length; i++) { + cp.newDouble(v[i]); + } + } else { + cp.newConst(value); + } + av.visit(name, value); + } + + public void visitEnum( + final String name, + final String desc, + final String value) + { + if (name != null) { + cp.newUTF8(name); + } + cp.newUTF8(desc); + cp.newUTF8(value); + av.visitEnum(name, desc, value); + } + + public AnnotationVisitor visitAnnotation( + final String name, + final String desc) + { + if (name != null) { + cp.newUTF8(name); + } + cp.newUTF8(desc); + return new AnnotationConstantsCollector(av.visitAnnotation(name, desc), + cp); + } + + public AnnotationVisitor visitArray(final String name) { + if (name != null) { + cp.newUTF8(name); + } + return new AnnotationConstantsCollector(av.visitArray(name), cp); + } + + public void visitEnd() { + av.visitEnd(); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ClassConstantsCollector.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ClassConstantsCollector.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ClassConstantsCollector.java 2007-01-07 13:44:08 UTC (rev 3030) @@ -0,0 +1,212 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.optimizer; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassAdapter; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +/** + * A {@link ClassVisitor} that collects the {@link Constant}s of the classes it + * visits. + * + * @author Eric Bruneton + */ +public class ClassConstantsCollector extends ClassAdapter { + + private ConstantPool cp; + + public ClassConstantsCollector(final ClassVisitor cv, final ConstantPool cp) + { + super(cv); + this.cp = cp; + } + + public void visit( + final int version, + final int access, + final String name, + final String signature, + final String superName, + final String[] interfaces) + { + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + cp.newUTF8("Deprecated"); + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + cp.newUTF8("Synthetic"); + } + cp.newClass(name); + if (signature != null) { + cp.newUTF8("Signature"); + cp.newUTF8(signature); + } + if (superName != null) { + cp.newClass(superName); + } + if (interfaces != null) { + for (int i = 0; i < interfaces.length; ++i) { + cp.newClass(interfaces[i]); + } + } + cv.visit(version, access, name, signature, superName, interfaces); + } + + public void visitSource(final String source, final String debug) { + if (source != null) { + cp.newUTF8("SourceFile"); + cp.newUTF8(source); + } + if (debug != null) { + cp.newUTF8("SourceDebugExtension"); + } + cv.visitSource(source, debug); + } + + public void visitOuterClass( + final String owner, + final String name, + final String desc) + { + cp.newUTF8("EnclosingMethod"); + cp.newClass(owner); + if (name != null && desc != null) { + cp.newNameType(name, desc); + } + cv.visitOuterClass(owner, name, desc); + } + + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + cp.newUTF8(desc); + if (visible) { + cp.newUTF8("RuntimeVisibleAnnotations"); + } else { + cp.newUTF8("RuntimeInvisibleAnnotations"); + } + return new AnnotationConstantsCollector(cv.visitAnnotation(desc, + visible), cp); + } + + public void visitAttribute(final Attribute attr) { + // can do nothing + cv.visitAttribute(attr); + } + + public void visitInnerClass( + final String name, + final String outerName, + final String innerName, + final int access) + { + cp.newUTF8("InnerClasses"); + if (name != null) { + cp.newClass(name); + } + if (outerName != null) { + cp.newClass(outerName); + } + if (innerName != null) { + cp.newClass(innerName); + } + cv.visitInnerClass(name, outerName, innerName, access); + } + + public FieldVisitor visitField( + final int access, + final String name, + final String desc, + final String signature, + final Object value) + { + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + cp.newUTF8("Synthetic"); + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + cp.newUTF8("Deprecated"); + } + cp.newUTF8(name); + cp.newUTF8(desc); + if (signature != null) { + cp.newUTF8("Signature"); + cp.newUTF8(signature); + } + if (value != null) { + cp.newConst(value); + } + return new FieldConstantsCollector(cv.visitField(access, + name, + desc, + signature, + value), cp); + } + + public MethodVisitor visitMethod( + final int access, + final String name, + final String desc, + final String signature, + final String[] exceptions) + { + if ((access & Opcodes.ACC_SYNTHETIC) != 0) { + cp.newUTF8("Synthetic"); + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + cp.newUTF8("Deprecated"); + } + cp.newUTF8(name); + cp.newUTF8(desc); + if (signature != null) { + cp.newUTF8("Signature"); + cp.newUTF8(signature); + } + if (exceptions != null) { + cp.newUTF8("Exceptions"); + for (int i = 0; i < exceptions.length; ++i) { + cp.newClass(exceptions[i]); + } + } + return new MethodConstantsCollector(cv.visitMethod(access, + name, + desc, + signature, + exceptions), cp); + } + + public void visitEnd() { + cv.visitEnd(); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ClassOptimizer.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ClassOptimizer.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ClassOptimizer.java 2007-01-07 13:44:08 UTC (rev 3030) @@ -0,0 +1,182 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.optimizer; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassAdapter; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +/** + * A {@link ClassAdapter} that renames fields and methods, and removes debug + * info. + * + * @author Eric Bruneton + */ +public class ClassOptimizer extends ClassAdapter { + + private NameMapping mapping; + + private String className; + + private String pkgName; + + public ClassOptimizer(final ClassVisitor cv, final NameMapping mapping) { + super(cv); + this.mapping = mapping; + } + + public String getClassName() { + return className; + } + + // ------------------------------------------------------------------------ + // Overriden methods + // ------------------------------------------------------------------------ + + public void visit( + final int version, + final int access, + final String name, + final String signature, + final String superName, + final String[] interfaces) + { + className = name; + pkgName = name.substring(0, name.lastIndexOf('/')); + cv.visit(version, + access, + mapping.map(name), + null, + mapping.map(superName), + interfaces); + } + + public void visitSource(final String source, final String debug) { + // remove debug info + } + + public void visitOuterClass( + final String owner, + final String name, + final String desc) + { + // remove debug info + } + + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + throw new UnsupportedOperationException(); + } + + public void visitAttribute(final Attribute attr) { + // remove non standard attribute + } + + public void visitInnerClass( + final String name, + final String outerName, + final String innerName, + final int access) + { + // remove debug info + } + + public FieldVisitor visitField( + final int access, + final String name, + final String desc, + final String signature, + final Object value) + { + String s = className + "." + name; + if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) { + if ((access & Opcodes.ACC_FINAL) != 0 + && (access & Opcodes.ACC_STATIC) != 0 && desc.equals("I")) + { + return null; + } + if (pkgName.equals("org/objectweb/asm") + && mapping.map(s).equals(name)) + { + System.out.println("INFO: " + s + " could be renamed"); + } + cv.visitField(access, + mapping.map(s), + mapping.fix(desc), + null, + value); + } else { + if (!mapping.map(s).equals(name)) { + throw new RuntimeException("The public or protected field " + s + + " must not be renamed."); + } + cv.visitField(access, name, desc, null, value); + } + return null; // remove debug info + } + + public MethodVisitor visitMethod( + final int access, + final String name, + final String desc, + final String signature, + final String[] exceptions) + { + String s = className + "." + name + desc; + if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) { + if (pkgName.equals("org/objectweb/asm") && !name.startsWith("<") + && mapping.map(s).equals(name)) + { + System.out.println("INFO: " + s + " could be renamed"); + } + return new MethodOptimizer(cv.visitMethod(access, + mapping.map(s), + mapping.fix(desc), + null, + exceptions), mapping); + } else { + if (!mapping.map(s).equals(name)) { + throw new RuntimeException("The public or protected method " + + s + " must not be renamed."); + } + return new MethodOptimizer(cv.visitMethod(access, + name, + desc, + null, + exceptions), mapping); + } + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/optimizer/Constant.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/Constant.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/Constant.java 2007-01-07 13:44:08 UTC (rev 3030) @@ -0,0 +1,265 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.optimizer; + +import org.objectweb.asm.ClassWriter; + +/** + * A constant pool item. + * + * @author Eric Bruneton + */ +class Constant { + + /** + * Type of this constant pool item. A single class is used to represent all + * constant pool item types, in order to minimize the bytecode size of this + * package. The value of this field is I, J, F, D, S, s, C, T, G, M, or N + * (for Constant Integer, Long, Float, Double, STR, UTF8, Class, NameType, + * Fieldref, Methodref, or InterfaceMethodref constant pool items + * respectively). + */ + char type; + + /** + * Value of this item, for an integer item. + */ + int intVal; + + /** + * Value of this item, for a long item. + */ + long longVal; + + /** + * Value of this item, for a float item. + */ + float floatVal; + + /** + * Value of this item, for a double item. + */ + double doubleVal; + + /** + * First part of the value of this item, for items that do not hold a + * primitive value. + */ + String strVal1; + + /** + * Second part of the value of this item, for items that do not hold a + * primitive value. + */ + String strVal2; + + /** + * Third part of the value of this item, for items that do not hold a + * primitive value. + */ + String strVal3; + + /** + * The hash code value of this constant pool item. + */ + int hashCode; + + public Constant() { + } + + public Constant(final Constant i) { + type = i.type; + intVal = i.intVal; + longVal = i.longVal; + floatVal = i.floatVal; + doubleVal = i.doubleVal; + strVal1 = i.strVal1; + strVal2 = i.strVal2; + strVal3 = i.strVal3; + hashCode = i.hashCode; + } + + /** + * Sets this item to an integer item. + * + * @param intVal the value of this item. + */ + void set(final int intVal) { + this.type = 'I'; + this.intVal = intVal; + this.hashCode = 0x7FFFFFFF & (type + intVal); + } + + /** + * Sets this item to a long item. + * + * @param longVal the value of this item. + */ + void set(final long longVal) { + this.type = 'J'; + this.longVal = longVal; + this.hashCode = 0x7FFFFFFF & (type + (int) longVal); + } + + /** + * Sets this item to a float item. + * + * @param floatVal the value of this item. + */ + void set(final float floatVal) { + this.type = 'F'; + this.floatVal = floatVal; + this.hashCode = 0x7FFFFFFF & (type + (int) floatVal); + } + + /** + * Sets this item to a double item. + * + * @param doubleVal the value of this item. + */ + void set(final double doubleVal) { + this.type = 'D'; + this.doubleVal = doubleVal; + this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal); + } + + /** + * Sets this item to an item that do not hold a primitive value. + * + * @param type the type of this item. + * @param strVal1 first part of the value of this item. + * @param strVal2 second part of the value of this item. + * @param strVal3 third part of the value of this item. + */ + void set( + final char type, + final String strVal1, + final String strVal2, + final String strVal3) + { + this.type = type; + this.strVal1 = strVal1; + this.strVal2 = strVal2; + this.strVal3 = strVal3; + switch (type) { + case 's': + case 'S': + case 'C': + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); + return; + case 'T': + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() + * strVal2.hashCode()); + return; + // case 'G': + // case 'M': + // case 'N': + default: + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() + * strVal2.hashCode() * strVal3.hashCode()); + } + } + + void write(final ClassWriter cw) { + switch (type) { + case 'I': + cw.newConst(new Integer(intVal)); + break; + case 'J': + cw.newConst(new Long(longVal)); + break; + case 'F': + cw.newConst(new Float(floatVal)); + break; + case 'D': + cw.newConst(new Double(doubleVal)); + break; + case 'S': + cw.newConst(strVal1); + break; + case 's': + cw.newUTF8(strVal1); + break; + case 'C': + cw.newClass(strVal1); + break; + case 'T': + cw.newNameType(strVal1, strVal2); + break; + case 'G': + cw.newField(strVal1, strVal2, strVal3); + break; + case 'M': + cw.newMethod(strVal1, strVal2, strVal3, false); + break; + case 'N': + cw.newMethod(strVal1, strVal2, strVal3, true); + break; + } + } + + public boolean equals(final Object o) { + if (!(o instanceof Constant)) { + return false; + } + Constant c = (Constant) o; + if (c.type == type) { + switch (type) { + case 'I': + return c.intVal == intVal; + case 'J': + return c.longVal == longVal; + case 'F': + return c.floatVal == floatVal; + case 'D': + return c.doubleVal == doubleVal; + case 's': + case 'S': + case 'C': + return c.strVal1.equals(strVal1); + case 'T': + return c.strVal1.equals(strVal1) + && c.strVal2.equals(strVal2); + // case 'G': + // case 'M': + // case 'N': + default: + return c.strVal1.equals(strVal1) + && c.strVal2.equals(strVal2) + && c.strVal3.equals(strVal3); + } + } + return false; + } + + public int hashCode() { + return hashCode; + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ConstantPool.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ConstantPool.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/ConstantPool.java 2007-01-07 13:44:08 UTC (rev 3030) @@ -0,0 +1,198 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.optimizer; + +import java.util.HashMap; + +import org.objectweb.asm.Type; + +/** + * A constant pool. + * + * @author Eric Bruneton + */ +public class ConstantPool extends HashMap { + + private Constant key1 = new Constant(); + + private Constant key2 = new Constant(); + + private Constant key3 = new Constant(); + + public Constant newInteger(final int value) { + key1.set(value); + Constant result = get(key1); + if (result == null) { + result = new Constant(key1); + put(result); + } + return result; + } + + public Constant newFloat(final float value) { + key1.set(value); + Constant result = get(key1); + if (result == null) { + result = new Constant(key1); + put(result); + } + return result; + } + + public Constant newLong(final long value) { + key1.set(value); + Constant result = get(key1); + if (result == null) { + result = new Constant(key1); + put(result); + } + return result; + } + + public Constant newDouble(final double value) { + key1.set(value); + Constant result = get(key1); + if (result == null) { + result = new Constant(key1); + put(result); + } + return result; + } + + public Constant newUTF8(final String value) { + key1.set('s', value, null, null); + Constant result = get(key1); + if (result == null) { + result = new Constant(key1); + put(result); + } + return result; + } + + private Constant newString(final String value) { + key2.set('S', value, null, null); + Constant result = get(key2); + if (result == null) { + newUTF8(value); + result = new Constant(key2); + put(result); + } + return result; + } + + public Constant newClass(final String value) { + key2.set('C', value, null, null); + Constant result = get(key2); + if (result == null) { + newUTF8(value); + result = new Constant(key2); + put(result); + } + return result; + } + + public Constant newConst(final Object cst) { + if (cst instanceof Integer) { + int val = ((Integer) cst).intValue(); + return newInteger(val); + } else if (cst instanceof Float) { + float val = ((Float) cst).floatValue(); + return newFloat(val); + } else if (cst instanceof Long) { + long val = ((Long) cst).longValue(); + return newLong(val); + } else if (cst instanceof Double) { + double val = ((Double) cst).doubleValue(); + return newDouble(val); + } else if (cst instanceof String) { + return newString((String) cst); + } else if (cst instanceof Type) { + Type t = (Type) cst; + return newClass(t.getSort() == Type.OBJECT + ? t.getInternalName() + : t.getDescriptor()); + } else { + throw new IllegalArgumentException("value " + cst); + } + } + + public Constant newField( + final String owner, + final String name, + final String desc) + { + key3.set('G', owner, name, desc); + Constant result = get(key3); + if (result == null) { + newClass(owner); + newNameType(name, desc); + result = new Constant(key3); + put(result); + } + return result; + } + + public Constant newMethod( + final String owner, + final String name, + final String desc, + final boolean itf) + { + key3.set(itf ? 'N' : 'M', owner, name, desc); + Constant result = get(key3); + if (result == null) { + newClass(owner); + newNameType(name, desc); + result = new Constant(key3); + put(result); + } + return result; + } + + public Constant newNameType(final String name, final String desc) { + key2.set('T', name, desc, null); + Constant result = get(key2); + if (result == null) { + newUTF8(name); + newUTF8(desc); + result = new Constant(key2); + put(result); + } + return result; + } + + private Constant get(final Constant key) { + return (Constant) get((Object) key); + } + + private void put(final Constant cst) { + put(cst, cst); + } +} \ No newline at end of file Added: trunk/core/src/classpath/org/org/objectweb/asm/optimizer/FieldConstantsCollector.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/FieldConstantsCollector.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/FieldConstantsCollector.java 2007-01-07 13:44:08 UTC (rev 3030) @@ -0,0 +1,76 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.optimizer; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.FieldVisitor; + +/** + * A {@link FieldVisitor} that collects the {@link Constant}s of the fields it + * visits. + * + * @author Eric Bruneton + */ +public class FieldConstantsCollector implements FieldVisitor { + + private FieldVisitor fv; + + private ConstantPool cp; + + public FieldConstantsCollector(final FieldVisitor fv, final ConstantPool cp) + { + this.fv = fv; + this.cp = cp; + } + + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + cp.newUTF8(desc); + if (visible) { + cp.newUTF8("RuntimeVisibleAnnotations"); + } else { + cp.newUTF8("RuntimeInvisibleAnnotations"); + } + return new AnnotationConstantsCollector(fv.visitAnnotation(desc, + visible), cp); + } + + public void visitAttribute(final Attribute attr) { + // can do nothing + fv.visitAttribute(attr); + } + + public void visitEnd() { + fv.visitEnd(); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/optimizer/JarOptimizer.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/JarOptimizer.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/JarOptimizer.java 2007-01-07 13:44:08 UTC (rev 3030) @@ -0,0 +1,87 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.optimizer; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +/** + * A Jar file optimizer. + * + * @author Eric Bruneton + */ +public class JarOptimizer { + + public static void main(final String[] args) throws IOException { + File f = new File(args[0]); + optimize(f); + } + + static void optimize(final File f) throws IOException { + if (f.isDirectory()) { + File[] files = f.listFiles(); + for (int i = 0; i < files.length; ++i) { + optimize(files[i]); + } + } else if (f.getName().endsWith(".jar")) { + File g = new File(f.getParentFile(), f.getName() + ".new"); + ZipFile zf = new ZipFile(f); + ZipOutputStream out = new ZipOutputStream(new FileOutputStream(g)); + Enumeration e = zf.entries(); + byte[] buf = new byte[10000]; + while (e.hasMoreElements()) { + ZipEntry ze = (ZipEntry) e.nextElement(); + if (ze.isDirectory()) { + continue; + } + out.putNextEntry(ze); + InputStream is = zf.getInputStream(ze); + int n; + do { + n = is.read(buf, 0, buf.length); + if (n != -1) { + out.write(buf, 0, n); + } + } while (n != -1); + out.closeEntry(); + } + out.close(); + zf.close(); + f.delete(); + g.renameTo(f); + } + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/optimizer/MethodConstantsCollector.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/MethodConstantsCollector.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/MethodConstantsCollector.java 2007-01-07 13:44:08 UTC (rev 3030) @@ -0,0 +1,168 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.optimizer; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodAdapter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +/** + * An {@link MethodVisitor} that collects the {@link Constant}s of the methods + * it visits. + * + * @author Eric Bruneton + */ +public class MethodConstantsCollector extends MethodAdapter { + + private ConstantPool cp; + + public MethodConstantsCollector( + final MethodVisitor mv, + final ConstantPool cp) + { + super(mv); + this.cp = cp; + } + + public AnnotationVisitor visitAnnotationDefault() { + cp.newUTF8("AnnotationDefault"); + return new AnnotationConstantsCollector(mv.visitAnnotationDefault(), cp); + } + + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + cp.newUTF8(desc); + if (visible) { + cp.newUTF8("RuntimeVisibleAnnotations"); + } else { + cp.newUTF8("RuntimeInvisibleAnnotations"); + } + return new AnnotationConstantsCollector(mv.visitAnnotation(desc, + visible), cp); + } + + public AnnotationVisitor visitParameterAnnotation( + final int parameter, + final String desc, + final boolean visible) + { + cp.newUTF8(desc); + if (visible) { + cp.newUTF8("RuntimeVisibleParameterAnnotations"); + } else { + cp.newUTF8("RuntimeInvisibleParameterAnnotations"); + } + return new AnnotationConstantsCollector(mv.visitParameterAnnotation(parameter, + desc, + visible), + cp); + } + + public void visitTypeInsn(final int opcode, final String desc) { + cp.newClass(desc); + mv.visitTypeInsn(opcode, desc); + } + + public void visitFieldInsn( + final int opcode, + final String owner, + final String name, + final String desc) + { + cp.newField(owner, name, desc); + mv.visitFieldInsn(opcode, owner, name, desc); + } + + public void visitMethodInsn( + final int opcode, + final String owner, + final String name, + final String desc) + { + boolean itf = opcode == Opcodes.INVOKEINTERFACE; + cp.newMethod(owner, name, desc, itf); + mv.visitMethodInsn(opcode, owner, name, desc); + } + + public void visitLdcInsn(final Object cst) { + cp.newConst(cst); + mv.visitLdcInsn(cst); + } + + public void visitMultiANewArrayInsn(final String desc, final int dims) { + cp.newClass(desc); + mv.visitMultiANewArrayInsn(desc, dims); + } + + public void visitTryCatchBlock( + final Label start, + final Label end, + final Label handler, + final String type) + { + if (type != null) { + cp.newClass(type); + } + mv.visitTryCatchBlock(start, end, handler, type); + } + + public void visitLocalVariable( + final String name, + final String desc, + final String signature, + final Label start, + final Label end, + final int index) + { + if (signature != null) { + cp.newUTF8("LocalVariableTypeTable"); + cp.newUTF8(name); + cp.newUTF8(signature); + } + cp.newUTF8("LocalVariableTable"); + cp.newUTF8(name); + cp.newUTF8(desc); + mv.visitLocalVariable(name, desc, signature, start, end, index); + } + + public void visitLineNumber(final int line, final Label start) { + cp.newUTF8("LineNumberTable"); + mv.visitLineNumber(line, start); + } + + public void visitMaxs(final int maxStack, final int maxLocals) { + cp.newUTF8("Code"); + mv.visitMaxs(maxStack, maxLocals); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/optimizer/MethodOptimizer.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/MethodOptimizer.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/MethodOptimizer.java 2007-01-07 13:44:08 UTC (rev 3030) @@ -0,0 +1,108 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.optimizer; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodAdapter; +import org.objectweb.asm.MethodVisitor; + +/** + * A {@link MethodAdapter} that renames fields and methods, and removes debug + * info. + * + * @author Eric Bruneton + */ +public class MethodOptimizer extends MethodAdapter { + + private NameMapping mapping; + + public MethodOptimizer(final MethodVisitor mv, final NameMapping mapping) { + super(mv); + this.mapping = mapping; + } + + // ------------------------------------------------------------------------ + // Overriden methods + // ------------------------------------------------------------------------ + + public AnnotationVisitor visitAnnotationDefault() { + throw new UnsupportedOperationException(); + } + + public AnnotationVisitor visitParameterAnnotation( + final int parameter, + final String desc, + final boolean visible) + { + throw new UnsupportedOperationException(); + } + + public void visitTypeInsn(final int opcode, final String desc) { + mv.visitTypeInsn(opcode, desc.startsWith("[") + ? mapping.fix(desc) + : mapping.map(desc)); + } + + public void visitFieldInsn( + final int opcode, + final String owner, + final String name, + final String desc) + { + mv.visitFieldInsn(opcode, mapping.map(owner), mapping.map(owner + "." + + name), mapping.fix(desc)); + } + + public void visitMethodInsn( + final int opcode, + final String owner, + final String name, + final String desc) + { + mv.visitMethodInsn(opcode, mapping.map(owner), mapping.map(owner + "." + + name + desc), mapping.fix(desc)); + } + + public void visitLocalVariable( + final String name, + final String desc, + final String signature, + final Label start, + final Label end, + final int index) + { + // remove debug info + } + + public void visitLineNumber(final int line, final Label start) { + // remove debug info + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/optimizer/NameMapping.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/NameMapping.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/NameMapping.java 2007-01-07 13:44:08 UTC (rev 3030) @@ -0,0 +1,101 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.optimizer; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + +import org.objectweb.asm.Type; + +/** + * A mapping from names to names, used to rename classes, fields and methods. + * + * @author Eric Bruneton + */ +public class NameMapping extends Properties { + + public final Set unused; + + public NameMapping(final String file) throws IOException { + load(new FileInputStream(file)); + unused = new HashSet(keySet()); + } + + public String map(final String name) { + String s = (String) get(name); + if (s == null) { + int p = name.indexOf('.'); + if (p != -1) { + int q = name.indexOf('('); + if (q != -1) { + s = name.substring(p + 1, q); + } else { + s = name.substring(p + 1); + } + } else { + s = name; + } + } else { + unused.remove(name); + } + return s; + } + + public String fix(final String desc) { + if (desc.startsWith("(")) { + Type[] arguments = Type.getArgumentTypes(desc); + Type result = Type.getReturnType(desc); + for (int i = 0; i < arguments.length; ++i) { + arguments[i] = fix(arguments[i]); + } + result = fix(result); + return Type.getMethodDescriptor(result, arguments); + } else { + return fix(Type.getType(desc)).getDescriptor(); + } + } + + private Type fix(final Type t) { + if (t.getSort() == Type.OBJECT) { + return Type.getType("L" + map(t.getInternalName()) + ";"); + } else if (t.getSort() == Type.ARRAY) { + String s = fix(t.getElementType()).getDescriptor(); + for (int i = 0; i < t.getDimensions(); ++i) { + s = "[" + s; + } + return Type.getType(s); + } else { + return t; + } + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/optimizer/Shrinker.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/optimizer/Shrinker.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/optimizer/Shrinker.java 2007-01-07 13:44:08 UTC (rev 3030) @@ -0,0 +1,168 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.optimizer; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Comparator; ... [truncated message content] |
From: <ls...@us...> - 2007-01-07 13:40:32
|
Revision: 3029 http://jnode.svn.sourceforge.net/jnode/?rev=3029&view=rev Author: lsantha Date: 2007-01-07 05:40:30 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Added Paths: ----------- trunk/core/src/classpath/org/org/objectweb/asm/commons/ trunk/core/src/classpath/org/org/objectweb/asm/commons/AdviceAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/commons/EmptyVisitor.java trunk/core/src/classpath/org/org/objectweb/asm/commons/GeneratorAdapter.java trunk/core/src/classpath/org/org/objectweb/asm/commons/LocalVariablesSorter.java trunk/core/src/classpath/org/org/objectweb/asm/commons/Method.java trunk/core/src/classpath/org/org/objectweb/asm/commons/SerialVersionUIDAdder.java trunk/core/src/classpath/org/org/objectweb/asm/commons/StaticInitMerger.java trunk/core/src/classpath/org/org/objectweb/asm/commons/TableSwitchGenerator.java trunk/core/src/classpath/org/org/objectweb/asm/commons/package.html Added: trunk/core/src/classpath/org/org/objectweb/asm/commons/AdviceAdapter.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/commons/AdviceAdapter.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/commons/AdviceAdapter.java 2007-01-07 13:40:30 UTC (rev 3029) @@ -0,0 +1,643 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.commons; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * A <code>MethodAdapter</code> to dispatch method body instruction + * <p> + * The behavior is like this: + * <ol> + * + * <li>as long as the INVOKESPECIAL for the object initialization has not been + * reached, every bytecode instruction is dispatched in the ctor code visitor</li> + * + * <li>when this one is reached, it is only added in the ctor code visitor and + * a JP invoke is added</li> + * <li>after that, only the other code visitor receives the instructions</li> + * + * </ol> + * + * @author Eugene Kuleshov + * @author Eric Bruneton + */ +public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes { + private static final Object THIS = new Object(); + private static final Object OTHER = new Object(); + + protected int methodAccess; + protected String methodDesc; + + private boolean constructor; + private boolean superInitialized; + private ArrayList stackFrame; + private HashMap branches; + + + /** + * Creates a new {@link AdviceAdapter}. + * + * @param mv the method visitor to which this adapter delegates calls. + * @param access the method's access flags (see {@link Opcodes}). + * @param name the method's name. + * @param desc the method's descriptor (see {@link Type Type}). + */ + public AdviceAdapter(MethodVisitor mv, int access, String name, String desc) { + super(mv, access, name, desc); + methodAccess = access; + methodDesc = desc; + + constructor = "<init>".equals(name); + if (!constructor) { + superInitialized = true; + onMethodEnter(); + } else { + stackFrame = new ArrayList(); + branches = new HashMap(); + } + } + + public void visitLabel(Label label) { + mv.visitLabel(label); + + if (constructor && branches != null) { + ArrayList frame = (ArrayList) branches.get(label); + if (frame != null) { + stackFrame = frame; + branches.remove(label); + } + } + } + + public void visitInsn(int opcode) { + if (constructor) { + switch (opcode) { + case RETURN: // empty stack + onMethodExit(opcode); + break; + + case IRETURN: // 1 before n/a after + case FRETURN: // 1 before n/a after + case ARETURN: // 1 before n/a after + case ATHROW: // 1 before n/a after + popValue(); + popValue(); + onMethodExit(opcode); + break; + + case LRETURN: // 2 before n/a after + case DRETURN: // 2 before n/a after + popValue(); + popValue(); + onMethodExit(opcode); + break; + + case NOP: + case LALOAD: // remove 2 add 2 + case DALOAD: // remove 2 add 2 + case LNEG: + case DNEG: + case FNEG: + case INEG: + case L2D: + case D2L: + case F2I: + case I2B: + case I2C: + case I2S: + case I2F: + case Opcodes.ARRAYLENGTH: + break; + + case ACONST_NULL: + case ICONST_M1: + case ICONST_0: + case ICONST_1: + case ICONST_2: + case ICONST_3: + case ICONST_4: + case ICONST_5: + case FCONST_0: + case FCONST_1: + case FCONST_2: + case F2L: // 1 before 2 after + case F2D: + case I2L: + case I2D: + pushValue(OTHER); + break; + + case LCONST_0: + case LCONST_1: + case DCONST_0: + case DCONST_1: + pushValue(OTHER); + pushValue(OTHER); + break; + + case IALOAD: // remove 2 add 1 + case FALOAD: // remove 2 add 1 + case AALOAD: // remove 2 add 1 + case BALOAD: // remove 2 add 1 + case CALOAD: // remove 2 add 1 + case SALOAD: // remove 2 add 1 + case POP: + case IADD: + case FADD: + case ISUB: + case LSHL: // 3 before 2 after + case LSHR: // 3 before 2 after + case LUSHR: // 3 before 2 after + case L2I: // 2 before 1 after + case L2F: // 2 before 1 after + case D2I: // 2 before 1 after + case D2F: // 2 before 1 after + case FSUB: + case FMUL: + case FDIV: + case FREM: + case FCMPL: // 2 before 1 after + case FCMPG: // 2 before 1 after + case IMUL: + case IDIV: + case IREM: + case ISHL: + case ISHR: + case IUSHR: + case IAND: + case IOR: + case IXOR: + case MONITORENTER: + case MONITOREXIT: + popValue(); + break; + + case POP2: + case LSUB: + case LMUL: + case LDIV: + case LREM: + case LADD: + case LAND: + case LOR: + case LXOR: + case DADD: + case DMUL: + case DSUB: + case DDIV: + case DREM: + popValue(); + popValue(); + break; + + case IASTORE: + case FASTORE: + case AASTORE: + case BASTORE: + case CASTORE: + case SASTORE: + case LCMP: // 4 before 1 after + case DCMPL: + case DCMPG: + popValue(); + popValue(); + popValue(); + break; + + case LASTORE: + case DASTORE: + popValue(); + popValue(); + popValue(); + popValue(); + break; + + case DUP: + pushValue(peekValue()); + break; + + case DUP_X1: + // TODO optimize this + { + Object o1 = popValue(); + Object o2 = popValue(); + pushValue(o1); + pushValue(o2); + pushValue(o1); + } + break; + + case DUP_X2: + // TODO optimize this + { + Object o1 = popValue(); + Object o2 = popValue(); + Object o3 = popValue(); + pushValue(o1); + pushValue(o3); + pushValue(o2); + pushValue(o1); + } + break; + + case DUP2: + // TODO optimize this + { + Object o1 = popValue(); + Object o2 = popValue(); + pushValue(o2); + pushValue(o1); + pushValue(o2); + pushValue(o1); + } + break; + + case DUP2_X1: + // TODO optimize this + { + Object o1 = popValue(); + Object o2 = popValue(); + Object o3 = popValue(); + pushValue(o2); + pushValue(o1); + pushValue(o3); + pushValue(o2); + pushValue(o1); + } + break; + + case DUP2_X2: + // TODO optimize this + { + Object o1 = popValue(); + Object o2 = popValue(); + Object o3 = popValue(); + Object o4 = popValue(); + pushValue(o2); + pushValue(o1); + pushValue(o4); + pushValue(o3); + pushValue(o2); + pushValue(o1); + } + break; + + case SWAP: { + Object o1 = popValue(); + Object o2 = popValue(); + pushValue(o1); + pushValue(o2); + } + break; + } + } else { + switch (opcode) { + case RETURN: + case IRETURN: + case FRETURN: + case ARETURN: + case LRETURN: + case DRETURN: + case ATHROW: + onMethodExit(opcode); + break; + } + } + mv.visitInsn(opcode); + } + + public void visitVarInsn(int opcode, int var) { + super.visitVarInsn(opcode, var); + + if (constructor) { + switch (opcode) { + case ILOAD: + case FLOAD: + pushValue(OTHER); + break; + case LLOAD: + case DLOAD: + pushValue(OTHER); + pushValue(OTHER); + break; + case ALOAD: + pushValue(var == 0 ? THIS : OTHER); + break; + case ASTORE: + case ISTORE: + case FSTORE: + popValue(); + break; + case LSTORE: + case DSTORE: + popValue(); + popValue(); + break; + } + } + } + + public void visitFieldInsn( + int opcode, + String owner, + String name, + String desc) + { + mv.visitFieldInsn(opcode, owner, name, desc); + + if (constructor) { + char c = desc.charAt(0); + boolean longOrDouble = c == 'J' || c == 'D'; + switch (opcode) { + case GETSTATIC: + pushValue(OTHER); + if (longOrDouble) { + pushValue(OTHER); + } + break; + case PUTSTATIC: + popValue(); + if(longOrDouble) { + popValue(); + } + break; + case PUTFIELD: + popValue(); + if(longOrDouble) { + popValue(); + popValue(); + } + break; + // case GETFIELD: + default: + if (longOrDouble) { + pushValue(OTHER); + } + } + } + } + + public void visitIntInsn(int opcode, int operand) { + mv.visitIntInsn(opcode, operand); + + if (constructor) { + switch (opcode) { + case BIPUSH: + case SIPUSH: + pushValue(OTHER); + } + } + } + + public void visitLdcInsn(Object cst) { + mv.visitLdcInsn(cst); + + if (constructor) { + pushValue(OTHER); + if (cst instanceof Double || cst instanceof Long) { + pushValue(OTHER); + } + } + } + + public void visitMultiANewArrayInsn(String desc, int dims) { + mv.visitMultiANewArrayInsn(desc, dims); + + if (constructor) { + for (int i = 0; i < dims; i++) { + popValue(); + } + pushValue(OTHER); + } + } + + public void visitTypeInsn(int opcode, String name) { + mv.visitTypeInsn(opcode, name); + + // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack + if (constructor && opcode == NEW) { + pushValue(OTHER); + } + } + + public void visitMethodInsn( + int opcode, + String owner, + String name, + String desc) + { + mv.visitMethodInsn(opcode, owner, name, desc); + + if (constructor) { + Type[] types = Type.getArgumentTypes(desc); + for (int i = 0; i < types.length; i++) { + popValue(); + if (types[i].getSize() == 2) { + popValue(); + } + } + switch (opcode) { + // case INVOKESTATIC: + // break; + + case INVOKEINTERFACE: + case INVOKEVIRTUAL: + popValue(); // objectref + break; + + case INVOKESPECIAL: + Object type = popValue(); // objectref + if (type == THIS && !superInitialized) { + onMethodEnter(); + superInitialized = true; + // once super has been initialized it is no longer + // necessary to keep track of stack state + constructor = false; + } + break; + } + + Type returnType = Type.getReturnType(desc); + if (returnType != Type.VOID_TYPE) { + pushValue(OTHER); + if (returnType.getSize() == 2) { + pushValue(OTHER); + } + } + } + } + + public void visitJumpInsn(int opcode, Label label) { + mv.visitJumpInsn(opcode, label); + + if (constructor) { + switch (opcode) { + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case IFNULL: + case IFNONNULL: + popValue(); + break; + + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + case IF_ACMPEQ: + case IF_ACMPNE: + popValue(); + popValue(); + break; + + case JSR: + pushValue(OTHER); + break; + } + addBranch(label); + } + } + + public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { + mv.visitLookupSwitchInsn(dflt, keys, labels); + + if (constructor) { + popValue(); + addBranches(dflt, labels); + } + } + + public void visitTableSwitchInsn( + int min, + int max, + Label dflt, + Label[] labels) + { + mv.visitTableSwitchInsn(min, max, dflt, labels); + + if (constructor) { + popValue(); + addBranches(dflt, labels); + } + } + + private void addBranches(Label dflt, Label[] labels) { + addBranch(dflt); + for (int i = 0; i < labels.length; i++) { + addBranch(labels[i]); + } + } + + private void addBranch(Label label) { + if (branches.containsKey(label)) { + return; + } + ArrayList frame = new ArrayList(); + frame.addAll(stackFrame); + branches.put(label, frame); + } + + private Object popValue() { + return stackFrame.remove(stackFrame.size()-1); + } + + private Object peekValue() { + return stackFrame.get(stackFrame.size()-1); + } + + private void pushValue(Object o) { + stackFrame.add(o); + } + + /** + * Called at the beginning of the method or after super + * class class call in the constructor. + * <br><br> + * + * <i>Custom code can use or change all the local variables, + * but should not change state of the stack.</i> + */ + protected abstract void onMethodEnter(); + + /** + * Called before explicit exit from the method using either + * return or throw. Top element on the stack contains the + * return value or exception instance. For example: + * + * <pre> + * public void onMethodExit(int opcode) { + * if(opcode==RETURN) { + * visitInsn(ACONST_NULL); + * } else if(opcode==ARETURN || opcode==ATHROW) { + * dup(); + * } else { + * if(opcode==LRETURN || opcode==DRETURN) { + * dup2(); + * } else { + * dup(); + * } + * box(Type.getReturnType(this.methodDesc)); + * } + * visitIntInsn(SIPUSH, opcode); + * visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V"); + * } + * + * // an actual call back method + * public static void onExit(int opcode, Object param) { + * ... + * </pre> + * + * <br><br> + * + * <i>Custom code can use or change all the local variables, + * but should not change state of the stack.</i> + * + * @param opcode one of the RETURN, IRETURN, FRETURN, + * ARETURN, LRETURN, DRETURN or ATHROW + * + */ + protected abstract void onMethodExit(int opcode); + + // TODO onException, onMethodCall + +} + Added: trunk/core/src/classpath/org/org/objectweb/asm/commons/EmptyVisitor.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/commons/EmptyVisitor.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/commons/EmptyVisitor.java 2007-01-07 13:40:30 UTC (rev 3029) @@ -0,0 +1,211 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.commons; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +/** + * An empty implementation of the ASM visitor interfaces. + * + * @author Eric Bruneton + */ +public class EmptyVisitor implements + ClassVisitor, + FieldVisitor, + MethodVisitor, + AnnotationVisitor +{ + + public void visit( + int version, + int access, + String name, + String signature, + String superName, + String[] interfaces) + { + } + + public void visitSource(String source, String debug) { + } + + public void visitOuterClass(String owner, String name, String desc) { + } + + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + return this; + } + + public void visitAttribute(Attribute attr) { + } + + public void visitInnerClass( + String name, + String outerName, + String innerName, + int access) + { + } + + public FieldVisitor visitField( + int access, + String name, + String desc, + String signature, + Object value) + { + return this; + } + + public MethodVisitor visitMethod( + int access, + String name, + String desc, + String signature, + String[] exceptions) + { + return this; + } + + public void visitEnd() { + } + + public AnnotationVisitor visitAnnotationDefault() { + return this; + } + + public AnnotationVisitor visitParameterAnnotation( + int parameter, + String desc, + boolean visible) + { + return this; + } + + public void visitCode() { + } + + public void visitInsn(int opcode) { + } + + public void visitIntInsn(int opcode, int operand) { + } + + public void visitVarInsn(int opcode, int var) { + } + + public void visitTypeInsn(int opcode, String desc) { + } + + public void visitFieldInsn( + int opcode, + String owner, + String name, + String desc) + { + } + + public void visitMethodInsn( + int opcode, + String owner, + String name, + String desc) + { + } + + public void visitJumpInsn(int opcode, Label label) { + } + + public void visitLabel(Label label) { + } + + public void visitLdcInsn(Object cst) { + } + + public void visitIincInsn(int var, int increment) { + } + + public void visitTableSwitchInsn( + int min, + int max, + Label dflt, + Label labels[]) + { + } + + public void visitLookupSwitchInsn(Label dflt, int keys[], Label labels[]) { + } + + public void visitMultiANewArrayInsn(String desc, int dims) { + } + + public void visitTryCatchBlock( + Label start, + Label end, + Label handler, + String type) + { + } + + public void visitLocalVariable( + String name, + String desc, + String signature, + Label start, + Label end, + int index) + { + } + + public void visitLineNumber(int line, Label start) { + } + + public void visitMaxs(int maxStack, int maxLocals) { + } + + public void visit(String name, Object value) { + } + + public void visitEnum(String name, String desc, String value) { + } + + public AnnotationVisitor visitAnnotation(String name, String desc) { + return this; + } + + public AnnotationVisitor visitArray(String name) { + return this; + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/commons/GeneratorAdapter.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/commons/GeneratorAdapter.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/commons/GeneratorAdapter.java 2007-01-07 13:40:30 UTC (rev 3029) @@ -0,0 +1,1454 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.commons; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * A {@link org.objectweb.asm.MethodAdapter} with convenient methods to generate + * code. For example, using this adapter, the class below + * + * <pre> + * public class Example { + * public static void main(String[] args) { + * System.out.println("Hello world!"); + * } + * } + * </pre> + * + * can be generated as follows: + * + * <pre> + * ClassWriter cw = new ClassWriter(true); + * cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null); + * + * Method m = Method.getMethod("void <init> ()"); + * GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw); + * mg.loadThis(); + * mg.invokeConstructor(Type.getType(Object.class), m); + * mg.returnValue(); + * mg.endMethod(); + * + * m = Method.getMethod("void main (String[])"); + * mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw); + * mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class)); + * mg.push("Hello world!"); + * mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)")); + * mg.returnValue(); + * mg.endMethod(); + * + * cw.visitEnd(); + * </pre> + * + * @author Juozas Baliuka + * @author Chris Nokleberg + * @author Eric Bruneton + */ +public class GeneratorAdapter extends LocalVariablesSorter { + + private final static Type BYTE_TYPE = Type.getType("Ljava/lang/Byte;"); + + private final static Type BOOLEAN_TYPE = Type.getType("Ljava/lang/Boolean;"); + + private final static Type SHORT_TYPE = Type.getType("Ljava/lang/Short;"); + + private final static Type CHARACTER_TYPE = Type.getType("Ljava/lang/Character;"); + + private final static Type INTEGER_TYPE = Type.getType("Ljava/lang/Integer;"); + + private final static Type FLOAT_TYPE = Type.getType("Ljava/lang/Float;"); + + private final static Type LONG_TYPE = Type.getType("Ljava/lang/Long;"); + + private final static Type DOUBLE_TYPE = Type.getType("Ljava/lang/Double;"); + + private final static Type NUMBER_TYPE = Type.getType("Ljava/lang/Number;"); + + private final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;"); + + private final static Method BOOLEAN_VALUE = Method.getMethod("boolean booleanValue()"); + + private final static Method CHAR_VALUE = Method.getMethod("char charValue()"); + + private final static Method INT_VALUE = Method.getMethod("int intValue()"); + + private final static Method FLOAT_VALUE = Method.getMethod("float floatValue()"); + + private final static Method LONG_VALUE = Method.getMethod("long longValue()"); + + private final static Method DOUBLE_VALUE = Method.getMethod("double doubleValue()"); + + /** + * Constant for the {@link #math math} method. + */ + public final static int ADD = Opcodes.IADD; + + /** + * Constant for the {@link #math math} method. + */ + public final static int SUB = Opcodes.ISUB; + + /** + * Constant for the {@link #math math} method. + */ + public final static int MUL = Opcodes.IMUL; + + /** + * Constant for the {@link #math math} method. + */ + public final static int DIV = Opcodes.IDIV; + + /** + * Constant for the {@link #math math} method. + */ + public final static int REM = Opcodes.IREM; + + /** + * Constant for the {@link #math math} method. + */ + public final static int NEG = Opcodes.INEG; + + /** + * Constant for the {@link #math math} method. + */ + public final static int SHL = Opcodes.ISHL; + + /** + * Constant for the {@link #math math} method. + */ + public final static int SHR = Opcodes.ISHR; + + /** + * Constant for the {@link #math math} method. + */ + public final static int USHR = Opcodes.IUSHR; + + /** + * Constant for the {@link #math math} method. + */ + public final static int AND = Opcodes.IAND; + + /** + * Constant for the {@link #math math} method. + */ + public final static int OR = Opcodes.IOR; + + /** + * Constant for the {@link #math math} method. + */ + public final static int XOR = Opcodes.IXOR; + + /** + * Constant for the {@link #ifCmp ifCmp} method. + */ + public final static int EQ = Opcodes.IFEQ; + + /** + * Constant for the {@link #ifCmp ifCmp} method. + */ + public final static int NE = Opcodes.IFNE; + + /** + * Constant for the {@link #ifCmp ifCmp} method. + */ + public final static int LT = Opcodes.IFLT; + + /** + * Constant for the {@link #ifCmp ifCmp} method. + */ + public final static int GE = Opcodes.IFGE; + + /** + * Constant for the {@link #ifCmp ifCmp} method. + */ + public final static int GT = Opcodes.IFGT; + + /** + * Constant for the {@link #ifCmp ifCmp} method. + */ + public final static int LE = Opcodes.IFLE; + + /** + * Access flags of the method visited by this adapter. + */ + private final int access; + + /** + * Return type of the method visited by this adapter. + */ + private final Type returnType; + + /** + * Argument types of the method visited by this adapter. + */ + private final Type[] argumentTypes; + + /** + * Types of the local variables of the method visited by this adapter. + */ + private final List localTypes; + + /** + * Creates a new {@link GeneratorAdapter}. + * + * @param mv the method visitor to which this adapter delegates calls. + * @param access the method's access flags (see {@link Opcodes}). + * @param name the method's name. + * @param desc the method's descriptor (see {@link Type Type}). + */ + public GeneratorAdapter( + MethodVisitor mv, + int access, + String name, + String desc) + { + super(access, desc, mv); + this.access = access; + this.returnType = Type.getReturnType(desc); + this.argumentTypes = Type.getArgumentTypes(desc); + this.localTypes = new ArrayList(); + } + + /** + * Creates a new {@link GeneratorAdapter}. + * + * @param access access flags of the adapted method. + * @param method the adapted method. + * @param mv the method visitor to which this adapter delegates calls. + */ + public GeneratorAdapter( + final int access, + final Method method, + final MethodVisitor mv) + { + super(access, method.getDescriptor(), mv); + this.access = access; + this.returnType = method.getReturnType(); + this.argumentTypes = method.getArgumentTypes(); + this.localTypes = new ArrayList(); + } + + /** + * Creates a new {@link GeneratorAdapter}. + * + * @param access access flags of the adapted method. + * @param method the adapted method. + * @param signature the signature of the adapted method (may be + * <tt>null</tt>). + * @param exceptions the exceptions thrown by the adapted method (may be + * <tt>null</tt>). + * @param cv the class visitor to which this adapter delegates calls. + */ + public GeneratorAdapter( + final int access, + final Method method, + final String signature, + final Type[] exceptions, + final ClassVisitor cv) + { + this(access, method, cv.visitMethod(access, + method.getName(), + method.getDescriptor(), + signature, + getInternalNames(exceptions))); + } + + /** + * Returns the internal names of the given types. + * + * @param types a set of types. + * @return the internal names of the given types. + */ + private static String[] getInternalNames(final Type[] types) { + if (types == null) { + return null; + } + String[] names = new String[types.length]; + for (int i = 0; i < names.length; ++i) { + names[i] = types[i].getInternalName(); + } + return names; + } + + // ------------------------------------------------------------------------ + // Instructions to push constants on the stack + // ------------------------------------------------------------------------ + + /** + * Generates the instruction to push the given value on the stack. + * + * @param value the value to be pushed on the stack. + */ + public void push(final boolean value) { + push(value ? 1 : 0); + } + + /** + * Generates the instruction to push the given value on the stack. + * + * @param value the value to be pushed on the stack. + */ + public void push(final int value) { + if (value >= -1 && value <= 5) { + mv.visitInsn(Opcodes.ICONST_0 + value); + } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { + mv.visitIntInsn(Opcodes.BIPUSH, value); + } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { + mv.visitIntInsn(Opcodes.SIPUSH, value); + } else { + mv.visitLdcInsn(new Integer(value)); + } + } + + /** + * Generates the instruction to push the given value on the stack. + * + * @param value the value to be pushed on the stack. + */ + public void push(final long value) { + if (value == 0L || value == 1L) { + mv.visitInsn(Opcodes.LCONST_0 + (int) value); + } else { + mv.visitLdcInsn(new Long(value)); + } + } + + /** + * Generates the instruction to push the given value on the stack. + * + * @param value the value to be pushed on the stack. + */ + public void push(final float value) { + int bits = Float.floatToIntBits(value); + if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2 + mv.visitInsn(Opcodes.FCONST_0 + (int) value); + } else { + mv.visitLdcInsn(new Float(value)); + } + } + + /** + * Generates the instruction to push the given value on the stack. + * + * @param value the value to be pushed on the stack. + */ + public void push(final double value) { + long bits = Double.doubleToLongBits(value); + if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d + mv.visitInsn(Opcodes.DCONST_0 + (int) value); + } else { + mv.visitLdcInsn(new Double(value)); + } + } + + /** + * Generates the instruction to push the given value on the stack. + * + * @param value the value to be pushed on the stack. May be <tt>null</tt>. + */ + public void push(final String value) { + if (value == null) { + mv.visitInsn(Opcodes.ACONST_NULL); + } else { + mv.visitLdcInsn(value); + } + } + + /** + * Generates the instruction to push the given value on the stack. + * + * @param value the value to be pushed on the stack. + */ + public void push(final Type value) { + if (value == null) { + mv.visitInsn(Opcodes.ACONST_NULL); + } else { + mv.visitLdcInsn(value); + } + } + + // ------------------------------------------------------------------------ + // Instructions to load and store method arguments + // ------------------------------------------------------------------------ + + /** + * Returns the index of the given method argument in the frame's local + * variables array. + * + * @param arg the index of a method argument. + * @return the index of the given method argument in the frame's local + * variables array. + */ + private int getArgIndex(final int arg) { + int index = ((access & Opcodes.ACC_STATIC) == 0 ? 1 : 0); + for (int i = 0; i < arg; i++) { + index += argumentTypes[i].getSize(); + } + return index; + } + + /** + * Generates the instruction to push a local variable on the stack. + * + * @param type the type of the local variable to be loaded. + * @param index an index in the frame's local variables array. + */ + private void loadInsn(final Type type, final int index) { + mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index); + } + + /** + * Generates the instruction to store the top stack value in a local + * variable. + * + * @param type the type of the local variable to be stored. + * @param index an index in the frame's local variables array. + */ + private void storeInsn(final Type type, final int index) { + mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index); + } + + /** + * Generates the instruction to load 'this' on the stack. + */ + public void loadThis() { + if ((access & Opcodes.ACC_STATIC) != 0) { + throw new IllegalStateException("no 'this' pointer within static method"); + } + mv.visitVarInsn(Opcodes.ALOAD, 0); + } + + /** + * Generates the instruction to load the given method argument on the stack. + * + * @param arg the index of a method argument. + */ + public void loadArg(final int arg) { + loadInsn(argumentTypes[arg], getArgIndex(arg)); + } + + /** + * Generates the instructions to load the given method arguments on the + * stack. + * + * @param arg the index of the first method argument to be loaded. + * @param count the number of method arguments to be loaded. + */ + public void loadArgs(final int arg, final int count) { + int index = getArgIndex(arg); + for (int i = 0; i < count; ++i) { + Type t = argumentTypes[arg + i]; + loadInsn(t, index); + index += t.getSize(); + } + } + + /** + * Generates the instructions to load all the method arguments on the stack. + */ + public void loadArgs() { + loadArgs(0, argumentTypes.length); + } + + /** + * Generates the instructions to load all the method arguments on the stack, + * as a single object array. + */ + public void loadArgArray() { + push(argumentTypes.length); + newArray(OBJECT_TYPE); + for (int i = 0; i < argumentTypes.length; i++) { + dup(); + push(i); + loadArg(i); + box(argumentTypes[i]); + arrayStore(OBJECT_TYPE); + } + } + + /** + * Generates the instruction to store the top stack value in the given + * method argument. + * + * @param arg the index of a method argument. + */ + public void storeArg(final int arg) { + storeInsn(argumentTypes[arg], getArgIndex(arg)); + } + + // ------------------------------------------------------------------------ + // Instructions to load and store local variables + // ------------------------------------------------------------------------ + + /** + * Creates a new local variable of the given type. + * + * @param type the type of the local variable to be created. + * @return the identifier of the newly created local variable. + */ + public int newLocal(final Type type) { + int local = super.newLocal(type.getSize()); + setLocalType(local, type); + return local; + } + + /** + * Returns the type of the given local variable. + * + * @param local a local variable identifier, as returned by {@link #newLocal + * newLocal}. + * @return the type of the given local variable. + */ + public Type getLocalType(final int local) { + return (Type) localTypes.get(local - firstLocal); + } + + /** + * Sets the current type of the given local variable. + * + * @param local a local variable identifier, as returned by {@link #newLocal + * newLocal}. + * @param type the type of the value being stored in the local variable + */ + private void setLocalType(final int local, final Type type) { + int index = local - firstLocal; + while (localTypes.size() < index + 1) + localTypes.add(null); + localTypes.set(index, type); + } + + /** + * Generates the instruction to load the given local variable on the stack. + * + * @param local a local variable identifier, as returned by {@link #newLocal + * newLocal}. + */ + public void loadLocal(final int local) { + loadInsn(getLocalType(local), local); + } + + /** + * Generates the instruction to load the given local variable on the stack. + * + * @param local a local variable identifier, as returned by {@link #newLocal + * newLocal}. + * @param type the type of this local variable. + */ + public void loadLocal(final int local, final Type type) { + setLocalType(local, type); + loadInsn(type, local); + } + + /** + * Generates the instruction to store the top stack value in the given local + * variable. + * + * @param local a local variable identifier, as returned by {@link #newLocal + * newLocal}. + */ + public void storeLocal(final int local) { + storeInsn(getLocalType(local), local); + } + + /** + * Generates the instruction to store the top stack value in the given local + * variable. + * + * @param local a local variable identifier, as returned by {@link #newLocal + * newLocal}. + * @param type the type of this local variable. + */ + public void storeLocal(final int local, final Type type) { + setLocalType(local, type); + storeInsn(type, local); + } + + /** + * Generates the instruction to load an element from an array. + * + * @param type the type of the array element to be loaded. + */ + public void arrayLoad(final Type type) { + mv.visitInsn(type.getOpcode(Opcodes.IALOAD)); + } + + /** + * Generates the instruction to store an element in an array. + * + * @param type the type of the array element to be stored. + */ + public void arrayStore(final Type type) { + mv.visitInsn(type.getOpcode(Opcodes.IASTORE)); + } + + // ------------------------------------------------------------------------ + // Instructions to manage the stack + // ------------------------------------------------------------------------ + + /** + * Generates a POP instruction. + */ + public void pop() { + mv.visitInsn(Opcodes.POP); + } + + /** + * Generates a POP2 instruction. + */ + public void pop2() { + mv.visitInsn(Opcodes.POP2); + } + + /** + * Generates a DUP instruction. + */ + public void dup() { + mv.visitInsn(Opcodes.DUP); + } + + /** + * Generates a DUP2 instruction. + */ + public void dup2() { + mv.visitInsn(Opcodes.DUP2); + } + + /** + * Generates a DUP_X1 instruction. + */ + public void dupX1() { + mv.visitInsn(Opcodes.DUP_X1); + } + + /** + * Generates a DUP_X2 instruction. + */ + public void dupX2() { + mv.visitInsn(Opcodes.DUP_X2); + } + + /** + * Generates a DUP2_X1 instruction. + */ + public void dup2X1() { + mv.visitInsn(Opcodes.DUP2_X1); + } + + /** + * Generates a DUP2_X2 instruction. + */ + public void dup2X2() { + mv.visitInsn(Opcodes.DUP2_X2); + } + + /** + * Generates a SWAP instruction. + */ + public void swap() { + mv.visitInsn(Opcodes.SWAP); + } + + /** + * Generates the instructions to swap the top two stack values. + * + * @param prev type of the top - 1 stack value. + * @param type type of the top stack value. + */ + public void swap(final Type prev, final Type type) { + if (type.getSize() == 1) { + if (prev.getSize() == 1) { + swap(); // same as dupX1(), pop(); + } else { + dupX2(); + pop(); + } + } else { + if (prev.getSize() == 1) { + dup2X1(); + pop2(); + } else { + dup2X2(); + pop2(); + } + } + } + + // ------------------------------------------------------------------------ + // Instructions to do mathematical and logical operations + // ------------------------------------------------------------------------ + + /** + * Generates the instruction to do the specified mathematical or logical + * operation. + * + * @param op a mathematical or logical operation. Must be one of ADD, SUB, + * MUL, DIV, REM, NEG, SHL, SHR, USHR, AND, OR, XOR. + * @param type the type of the operand(s) for this operation. + */ + public void math(final int op, final Type type) { + mv.visitInsn(type.getOpcode(op)); + } + + /** + * Generates the instructions to compute the bitwise negation of the top + * stack value. + */ + public void not() { + mv.visitInsn(Opcodes.ICONST_1); + mv.visitInsn(Opcodes.IXOR); + } + + /** + * Generates the instruction to increment the given local variable. + * + * @param local the local variable to be incremented. + * @param amount the amount by which the local variable must be incremented. + */ + public void iinc(final int local, final int amount) { + mv.visitIincInsn(local, amount); + } + + /** + * Generates the instructions to cast a numerical value from one type to + * another. + * + * @param from the type of the top stack value + * @param to the type into which this value must be cast. + */ + public void cast(final Type from, final Type to) { + if (from != to) { + if (from == Type.DOUBLE_TYPE) { + if (to == Type.FLOAT_TYPE) { + mv.visitInsn(Opcodes.D2F); + } else if (to == Type.LONG_TYPE) { + mv.visitInsn(Opcodes.D2L); + } else { + mv.visitInsn(Opcodes.D2I); + cast(Type.INT_TYPE, to); + } + } else if (from == Type.FLOAT_TYPE) { + if (to == Type.DOUBLE_TYPE) { + mv.visitInsn(Opcodes.F2D); + } else if (to == Type.LONG_TYPE) { + mv.visitInsn(Opcodes.F2L); + } else { + mv.visitInsn(Opcodes.F2I); + cast(Type.INT_TYPE, to); + } + } else if (from == Type.LONG_TYPE) { + if (to == Type.DOUBLE_TYPE) { + mv.visitInsn(Opcodes.L2D); + } else if (to == Type.FLOAT_TYPE) { + mv.visitInsn(Opcodes.L2F); + } else { + mv.visitInsn(Opcodes.L2I); + cast(Type.INT_TYPE, to); + } + } else { + if (to == Type.BYTE_TYPE) { + mv.visitInsn(Opcodes.I2B); + } else if (to == Type.CHAR_TYPE) { + mv.visitInsn(Opcodes.I2C); + } else if (to == Type.DOUBLE_TYPE) { + mv.visitInsn(Opcodes.I2D); + } else if (to == Type.FLOAT_TYPE) { + mv.visitInsn(Opcodes.I2F); + } else if (to == Type.LONG_TYPE) { + mv.visitInsn(Opcodes.I2L); + } else if (to == Type.SHORT_TYPE) { + mv.visitInsn(Opcodes.I2S); + } + } + } + } + + // ------------------------------------------------------------------------ + // Instructions to do boxing and unboxing operations + // ------------------------------------------------------------------------ + + /** + * Generates the instructions to box the top stack value. This value is + * replaced by its boxed equivalent on top of the stack. + * + * @param type the type of the top stack value. + */ + public void box(final Type type) { + if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { + return; + } + if (type == Type.VOID_TYPE) { + push((String) null); + } else { + Type boxed = type; + switch (type.getSort()) { + case Type.BYTE: + boxed = BYTE_TYPE; + break; + case Type.BOOLEAN: + boxed = BOOLEAN_TYPE; + break; + case Type.SHORT: + boxed = SHORT_TYPE; + break; + case Type.CHAR: + boxed = CHARACTER_TYPE; + break; + case Type.INT: + boxed = INTEGER_TYPE; + break; + case Type.FLOAT: + boxed = FLOAT_TYPE; + break; + case Type.LONG: + boxed = LONG_TYPE; + break; + case Type.DOUBLE: + boxed = DOUBLE_TYPE; + break; + } + newInstance(boxed); + if (type.getSize() == 2) { + // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o + dupX2(); + dupX2(); + pop(); + } else { + // p -> po -> opo -> oop -> o + dupX1(); + swap(); + } + invokeConstructor(boxed, new Method("<init>", + Type.VOID_TYPE, + new Type[] { type })); + } + } + + /** + * Generates the instructions to unbox the top stack value. This value is + * replaced by its unboxed equivalent on top of the stack. + * + * @param type the type of the top stack value. + */ + public void unbox(final Type type) { + Type t = NUMBER_TYPE; + Method sig = null; + switch (type.getSort()) { + case Type.VOID: + return; + case Type.CHAR: + t = CHARACTER_TYPE; + sig = CHAR_VALUE; + break; + case Type.BOOLEAN: + t = BOOLEAN_TYPE; + sig = BOOLEAN_VALUE; + break; + case Type.DOUBLE: + sig = DOUBLE_VALUE; + break; + case Type.FLOAT: + sig = FLOAT_VALUE; + break; + case Type.LONG: + sig = LONG_VALUE; + break; + case Type.INT: + case Type.SHORT: + case Type.BYTE: + sig = INT_VALUE; + } + if (sig == null) { + checkCast(type); + } else { + checkCast(t); + invokeVirtual(t, sig); + } + } + + // ------------------------------------------------------------------------ + // Instructions to jump to other instructions + // ------------------------------------------------------------------------ + + /** + * Creates a new {@link Label}. + * + * @return a new {@link Label}. + */ + public Label newLabel() { + return new Label(); + } + + /** + * Marks the current code position with the given label. + * + * @param label a label. + */ + public void mark(final Label label) { + mv.visitLabel(label); + } + + /** + * Marks the current code position with a new label. + * + * @return the label that was created to mark the current code position. + */ + public Label mark() { + Label label = new Label(); + mv.visitLabel(label); + return label; + } + + /** + * Generates the instructions to jump to a label based on the comparison of + * the top two stack values. + * + * @param type the type of the top two stack values. + * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT, + * LE. + * @param label where to jump if the comparison result is <tt>true</tt>. + */ + public void ifCmp(final Type type, final int mode, final Label label) { + int intOp = -1; + int jumpMode = mode; + switch (mode) { + case GE: + jumpMode = LT; + break; + case LE: + jumpMode = GT; + break; + } + switch (type.getSort()) { + case Type.LONG: + mv.visitInsn(Opcodes.LCMP); + break; + case Type.DOUBLE: + mv.visitInsn(Opcodes.DCMPG); + break; + case Type.FLOAT: + mv.visitInsn(Opcodes.FCMPG); + break; + case Type.ARRAY: + case Type.OBJECT: + switch (mode) { + case EQ: + mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label); + return; + case NE: + mv.visitJumpInsn(Opcodes.IF_ACMPNE, label); + return; + } + throw new IllegalArgumentException("Bad comparison for type " + + type); + default: + switch (mode) { + case EQ: + intOp = Opcodes.IF_ICMPEQ; + break; + case NE: + intOp = Opcodes.IF_ICMPNE; + break; + case GE: + intOp = Opcodes.IF_ICMPGE; + break; + case LT: + intOp = Opcodes.IF_ICMPLT; + break; + case LE: + intOp = Opcodes.IF_ICMPLE; + break; + case GT: + intOp = Opcodes.IF_ICMPGT; + break; + } + mv.visitJumpInsn(intOp, label); + return; + } + mv.visitJumpInsn(jumpMode, label); + } + + /** + * Generates the instructions to jump to a label based on the comparison of + * the top two integer stack values. + * + * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT, + * LE. + * @param label where to jump if the comparison result is <tt>true</tt>. + */ + public void ifICmp(final int mode, final Label label) { + ifCmp(Type.INT_TYPE, mode, label); + } + + /** + * Generates the instructions to jump to a label based on the comparison of + * the top integer stack value with zero. + * + * @param mode how the... [truncated message content] |
From: <ls...@us...> - 2007-01-07 13:36:57
|
Revision: 3028 http://jnode.svn.sourceforge.net/jnode/?rev=3028&view=rev Author: lsantha Date: 2007-01-07 05:36:55 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Added Paths: ----------- trunk/core/src/classpath/org/org/objectweb/ trunk/core/src/classpath/org/org/objectweb/asm/ trunk/core/src/classpath/org/org/objectweb/asm/attrs/ trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapAttribute.java trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapFrame.java trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapTableAttribute.java trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapType.java trunk/core/src/classpath/org/org/objectweb/asm/attrs/package.html Added: trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapAttribute.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapAttribute.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapAttribute.java 2007-01-07 13:36:55 UTC (rev 3028) @@ -0,0 +1,378 @@ +/** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.attrs; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ByteVector; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; + +/** + * StackMapAttribute is used by CDLC preverifier. Definition is given in + * appendix "CLDC Byte Code Typechecker Specification" from CDLC 1.1 + * specification. <p> <i>Note that this implementation does not calculate + * StackMapFrame structures from the method bytecode. If method code is changed + * or generated from scratch, then developer is responsible to prepare a correct + * StackMapFrame structures.</i> <p> The format of the stack map in the class + * file is given below. In the following, <ul> <li>if the length of the + * method's byte code1 is 65535 or less, then <tt>uoffset</tt> represents the + * type u2; otherwise <tt>uoffset</tt> represents the type u4.</li> <li>If + * the maximum number of local variables for the method is 65535 or less, then + * <tt>ulocalvar</tt> represents the type u2; otherwise <tt>ulocalvar</tt> + * represents the type u4.</li> <li>If the maximum size of the operand stack + * is 65535 or less, then <tt>ustack</tt> represents the type u2; otherwise + * ustack represents the type u4.</li> </ul> + * + * <pre> + * stack_map { // attribute StackMap + * u2 attribute_name_index; + * u4 attribute_length + * uoffset number_of_entries; + * stack_map_frame entries[number_of_entries]; + * } + * </pre> + * + * Each stack map frame has the following format: + * + * <pre> + * stack_map_frame { + * uoffset offset; + * ulocalvar number_of_locals; + * verification_type_info locals[number_of_locals]; + * ustack number_of_stack_items; + * verification_type_info stack[number_of_stack_items]; + * } + * </pre> + * + * The <tt>verification_type_info</tt> structure consists of a one-byte tag + * followed by zero or more bytes, giving more information about the tag. Each + * <tt>verification_type_info</tt> structure specifies the verification type + * of one or two locations. + * + * <pre> + * union verification_type_info { + * Top_variable_info; + * Integer_variable_info; + * Float_variable_info; + * Long_variable_info; + * Double_variable_info; + * Null_variable_info; + * UninitializedThis_variable_info; + * Object_variable_info; + * Uninitialized_variable_info; + * } + * + * Top_variable_info { + * u1 tag = ITEM_Top; // 0 + * } + * + * Integer_variable_info { + * u1 tag = ITEM_Integer; // 1 + * } + * + * Float_variable_info { + * u1 tag = ITEM_Float; // 2 + * } + * + * Long_variable_info { + * u1 tag = ITEM_Long; // 4 + * } + * + * Double_variable_info { + * u1 tag = ITEM_Double; // 3 + * } + * + * Null_variable_info { + * u1 tag = ITEM_Null; // 5 + * } + * + * UninitializedThis_variable_info { + * u1 tag = ITEM_UninitializedThis; // 6 + * } + * + * Object_variable_info { + * u1 tag = ITEM_Object; // 7 + * u2 cpool_index; + * } + * + * Uninitialized_variable_info { + * u1 tag = ITEM_Uninitialized // 8 + * uoffset offset; + * } + * </pre> + * + * @see <a href="http://www.jcp.org/en/jsr/detail?id=139">JSR 139 : Connected + * Limited Device Configuration 1.1</a> + * + * @author Eugene Kuleshov + */ +public class StackMapAttribute extends Attribute { + + static final int MAX_SIZE = 65535; + + /** + * A List of <code>StackMapFrame</code> instances. + */ + public List frames = new ArrayList(); + + public StackMapAttribute() { + super("StackMap"); + } + + public StackMapAttribute(List frames) { + this(); + this.frames = frames; + } + + public List getFrames() { + return frames; + } + + public StackMapFrame getFrame(Label label) { + for (int i = 0; i < frames.size(); i++) { + StackMapFrame frame = (StackMapFrame) frames.get(i); + if (frame.label == label) { + return frame; + } + } + return null; + } + + public boolean isUnknown() { + return false; + } + + public boolean isCodeAttribute() { + return true; + } + + protected Attribute read( + ClassReader cr, + int off, + int len, + char[] buf, + int codeOff, + Label[] labels) + { + StackMapAttribute attr = new StackMapAttribute(); + // note that this is not the size of Code attribute + boolean isExtCodeSize = cr.readInt(codeOff + 4) > MAX_SIZE; + boolean isExtLocals = cr.readUnsignedShort(codeOff + 2) > MAX_SIZE; + boolean isExtStack = cr.readUnsignedShort(codeOff) > MAX_SIZE; + + int size = 0; + if (isExtCodeSize) { + size = cr.readInt(off); + off += 4; + } else { + size = cr.readUnsignedShort(off); + off += 2; + } + for (int i = 0; i < size; i++) { + int offset; + if (isExtCodeSize) { + offset = cr.readInt(off); + off += 4; + } else { + offset = cr.readUnsignedShort(off); + off += 2; + } + + Label label = getLabel(offset, labels); + List locals = new ArrayList(); + List stack = new ArrayList(); + + off = readTypeInfo(cr, + off, + locals, + labels, + buf, + isExtLocals, + isExtCodeSize); + off = readTypeInfo(cr, + off, + stack, + labels, + buf, + isExtStack, + isExtCodeSize); + + attr.frames.add(new StackMapFrame(label, locals, stack)); + } + return attr; + } + + private int readTypeInfo( + ClassReader cr, + int off, + List info, + Label[] labels, + char[] buf, + boolean isExt, + boolean isExtCode) + { + int n = 0; + if (isExt) { + n = cr.readInt(off); + off += 4; + } else { + n = cr.readUnsignedShort(off); + off += 2; + } + for (int j = 0; j < n; j++) { + int itemType = cr.readByte(off++); + StackMapType typeInfo = StackMapType.getTypeInfo(itemType); + info.add(typeInfo); + switch (itemType) { + case StackMapType.ITEM_Object: // + typeInfo.setObject(cr.readClass(off, buf)); + off += 2; + break; + case StackMapType.ITEM_Uninitialized: // + int offset; + if (isExtCode) { + offset = cr.readInt(off); + off += 4; + } else { + offset = cr.readUnsignedShort(off); + off += 2; + } + typeInfo.setLabel(getLabel(offset, labels)); + break; + } + } + return off; + } + + private void writeTypeInfo(ByteVector bv, ClassWriter cw, List info, int max) + { + if (max > StackMapAttribute.MAX_SIZE) { + bv.putInt(info.size()); + } else { + bv.putShort(info.size()); + } + for (int j = 0; j < info.size(); j++) { + StackMapType typeInfo = (StackMapType) info.get(j); + bv.putByte(typeInfo.getType()); + switch (typeInfo.getType()) { + case StackMapType.ITEM_Object: // + bv.putShort(cw.newClass(typeInfo.getObject())); + break; + + case StackMapType.ITEM_Uninitialized: // + bv.putShort(typeInfo.getLabel().getOffset()); + break; + + } + } + } + + private Label getLabel(int offset, Label[] labels) { + Label l = labels[offset]; + if (l != null) { + return l; + } + return labels[offset] = new Label(); + } + + protected ByteVector write( + ClassWriter cw, + byte[] code, + int len, + int maxStack, + int maxLocals) + { + ByteVector bv = new ByteVector(); + if (code != null && code.length > MAX_SIZE) { // TODO verify value + bv.putInt(frames.size()); + } else { + bv.putShort(frames.size()); + } + for (int i = 0; i < frames.size(); i++) { + writeFrame((StackMapFrame) frames.get(i), + cw, + maxStack, + maxLocals, + bv); + } + return bv; + } + + protected Label[] getLabels() { + HashSet labels = new HashSet(); + for (int i = 0; i < frames.size(); i++) { + getFrameLabels((StackMapFrame) frames.get(i), labels); + } + return (Label[]) labels.toArray(new Label[labels.size()]); + } + + private void writeFrame( + StackMapFrame frame, + ClassWriter cw, + int maxStack, + int maxLocals, + ByteVector bv) + { + bv.putShort(frame.label.getOffset()); + writeTypeInfo(bv, cw, frame.locals, maxLocals); + writeTypeInfo(bv, cw, frame.stack, maxStack); + } + + private void getFrameLabels(StackMapFrame frame, Set labels) { + labels.add(frame.label); + getTypeInfoLabels(labels, frame.locals); + getTypeInfoLabels(labels, frame.stack); + } + + private void getTypeInfoLabels(Set labels, List info) { + for (Iterator it = info.iterator(); it.hasNext();) { + StackMapType typeInfo = (StackMapType) it.next(); + if (typeInfo.getType() == StackMapType.ITEM_Uninitialized) { + labels.add(typeInfo.getLabel()); + } + } + } + + public String toString() { + StringBuffer sb = new StringBuffer("StackMap["); + for (int i = 0; i < frames.size(); i++) { + sb.append('\n').append('[').append(frames.get(i)).append(']'); + } + sb.append("\n]"); + return sb.toString(); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapFrame.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapFrame.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapFrame.java 2007-01-07 13:36:55 UTC (rev 3028) @@ -0,0 +1,82 @@ +/** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.attrs; + +import java.util.List; + +import org.objectweb.asm.Label; + +/** + * Holds the state of the stack and local variables for a single execution + * branch. + * + * <i>Note that Long and Double types are represented by two entries in locals + * and stack. Second entry should be always of type Top.</i> + * + * @see <a href="http://www.jcp.org/en/jsr/detail?id=139">JSR 139 : Connected + * Limited Device Configuration 1.1</a> + * + * @see "ClassFileFormat-Java6.fm Page 138 Friday, April 15, 2005 3:22 PM" + * + * @author Eugene Kuleshov + */ +public class StackMapFrame { + + /** + * A <code>Label</code> for frame offset within method bytecode. + */ + public Label label; + + /** + * A List of <code>StackMapType</code> instances that represent locals for + * this frame. + */ + public List locals; + + /** + * A List of <code>StackMapType</code> instances that represent stack for + * this frame. + */ + public List stack; + + public StackMapFrame(Label label, List locals, List stack) { + this.label = label; + this.locals = locals; + this.stack = stack; + } + + public String toString() { + StringBuffer sb = new StringBuffer("Frame:L"); + sb.append(System.identityHashCode(label)); + sb.append(" locals").append(locals); + sb.append(" stack").append(stack); + return sb.toString(); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapTableAttribute.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapTableAttribute.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapTableAttribute.java 2007-01-07 13:36:55 UTC (rev 3028) @@ -0,0 +1,927 @@ +/** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.objectweb.asm.attrs; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ByteVector; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * The stack map attribute is used during the process of verification by + * typechecking (\xA74.11.1). <br> <br> A stack map attribute consists of zero or + * more stack map frames. Each stack map frame specifies (either explicitly or + * implicitly) a bytecode offset, the verification types (\xA74.11.1) for the local + * variables, and the verification types for the operand stack. <br> <br> The + * type checker deals with and manipulates the expected types of a method's + * local variables and operand stack. Throughout this section, a location refers + * to either a single local variable or to a single operand stack entry. <br> + * <br> We will use the terms stack frame map and type state interchangeably to + * describe a mapping from locations in the operand stack and local variables of + * a method to verification types. We will usually use the term stack frame map + * when such a mapping is provided in the class file, and the term type state + * when the mapping is inferred by the type checker. <br> <br> If a method's + * Code attribute does not have a StackMapTable attribute, it has an implicit + * stack map attribute. This implicit stack map attribute is equivalent to a + * StackMapTable attribute with number_of_entries equal to zero. A method's Code + * attribute may have at most one StackMapTable attribute, otherwise a + * java.lang.ClassFormatError is thrown. <br> <br> The format of the stack map + * in the class file is given below. In the following, if the length of the + * method's byte code is 65535 or less, then uoffset represents the type u2; + * otherwise uoffset represents the type u4. If the maximum number of local + * variables for the method is 65535 or less, then <code>ulocalvar</code> + * represents the type u2; otherwise ulocalvar represents the type u4. If the + * maximum size of the operand stack is 65535 or less, then <code>ustack</code> + * represents the type u2; otherwise ustack represents the type u4. + * + * <pre> + * stack_map { // attribute StackMapTable + * u2 attribute_name_index; + * u4 attribute_length + * uoffset number_of_entries; + * stack_map_frame entries[number_of_entries]; + * } + * </pre> + * + * Each stack_map_frame structure specifies the type state at a particular byte + * code offset. Each frame type specifies (explicitly or implicitly) a value, + * offset_delta, that is used to calulate the actual byte code offset at which + * it applies. The byte code offset at which the frame applies is given by + * adding <code>1 + offset_delta</code> to the <code>offset</code> of the + * previous frame, unless the previous frame is the initial frame of the method, + * in which case the byte code offset is <code>offset_delta</code>. <br> <br> + * <i>Note that the length of the byte codes is not the same as the length of + * the Code attribute. The byte codes are embedded in the Code attribute, along + * with other information.</i> <br> <br> By using an offset delta rather than + * the actual byte code offset we ensure, by definition, that stack map frames + * are in the correctly sorted order. Furthermore, by consistently using the + * formula <code>offset_delta + 1</code> for all explicit frames, we guarantee + * the absence of duplicates. <br> <br> All frame types, even full_frame, rely + * on the previous frame for some of their semantics. This raises the question + * of what is the very first frame? The initial frame is implicit, and computed + * from the method descriptor. See the Prolog code for methodInitialStacFrame. + * <br> <br> The stack_map_frame structure consists of a one-byte tag followed + * by zero or more bytes, giving more information, depending upon the tag. <br> + * <br> A stack map frame may belong to one of several frame types + * + * <pre> + * union stack_map_frame { + * same_frame; + * same_locals_1_stack_item_frame; + * chop_frame; + * same_frame_extended; + * append_frame; + * full_frame; + * } + * </pre> + * + * The frame type same_frame is represented by tags in the range [0-63]. If the + * frame type is same_frame, it means the frame has exactly the same locals as + * the previous stack map frame and that the number of stack items is zero. The + * offset_delta value for the frame is the value of the tag field, frame_type. + * The form of such a frame is then: + * + * <pre> + * same_frame { + * u1 frame_type = SAME; // 0-63 + * } + * </pre> + * + * The frame type same_locals_1_stack_item_frame is represented by tags in the + * range [64, 127]. If the frame_type is same_locals_1_stack_item_frame, it + * means the frame has exactly the same locals as the previous stack map frame + * and that the number of stack items is 1. The offset_delta value for the frame + * is the value (frame_type - 64). There is a verification_type_info following + * the frame_type for the one stack item. The form of such a frame is then: + * + * <pre> + * same_locals_1_stack_item_frame { + * u1 frame_type = SAME_LOCALS_1_STACK_ITEM; // 64-127 + * verification_type_info stack[1]; + * } + * </pre> + * + * Tags in the range [128-247] are reserved for future use. <br> <br> The frame + * type chop_frame is represented by tags in the range [248-250]. If the + * frame_type is chop_frame, it means that the current locals are the same as + * the locals in the previous frame, except that the k last locals are absent. + * The value of k is given by the formula 251-frame_type. <br> <br> The form of + * such a frame is then: + * + * <pre> + * chop_frame { + * u1 frame_type=CHOP; // 248-250 + * uoffset offset_delta; + * } + * </pre> + * + * The frame type same_frame_extended is represented by the tag value 251. If + * the frame type is same_frame_extended, it means the frame has exactly the + * same locals as the previous stack map frame and that the number of stack + * items is zero. The form of such a frame is then: + * + * <pre> + * same_frame_extended { + * u1 frame_type = SAME_FRAME_EXTENDED; // 251 + * uoffset offset_delta; + * } + * </pre> + * + * The frame type append_frame is represented by tags in the range [252-254]. If + * the frame_type is append_frame, it means that the current locals are the same + * as the locals in the previous frame, except that k additional locals are + * defined. The value of k is given by the formula frame_type-251. <br> <br> The + * form of such a frame is then: + * + * <pre> + * append_frame { + * u1 frame_type =APPEND; // 252-254 + * uoffset offset_delta; + * verification_type_info locals[frame_type -251]; + * } + * </pre> + * + * The 0th entry in locals represents the type of the first additional local + * variable. If locals[M] represents local variable N, then locals[M+1] + * represents local variable N+1 if locals[M] is one of Top_variable_info, + * Integer_variable_info, Float_variable_info, Null_variable_info, + * UninitializedThis_variable_info, Object_variable_info, or + * Uninitialized_variable_info, otherwise locals[M+1] represents local variable + * N+2. It is an error if, for any index i, locals[i] represents a local + * variable whose index is greater than the maximum number of local variables + * for the method. <br> <br> The frame type full_frame is represented by the tag + * value 255. The form of such a frame is then: + * + * <pre> + * full_frame { + * u1 frame_type = FULL_FRAME; // 255 + * uoffset offset_delta; + * ulocalvar number_of_locals; + * verification_type_info locals[number_of_locals]; + * ustack number_of_stack_items; + * verification_type_info stack[number_of_stack_items]; + * } + * </pre> + * + * The 0th entry in locals represents the type of local variable 0. If locals[M] + * represents local variable N, then locals[M+1] represents local variable N+1 + * if locals[M] is one of Top_variable_info, Integer_variable_info, + * Float_variable_info, Null_variable_info, UninitializedThis_variable_info, + * Object_variable_info, or Uninitialized_variable_info, otherwise locals[M+1] + * represents local variable N+2. It is an error if, for any index i, locals[i] + * represents a local variable whose index is greater than the maximum number of + * local variables for the method. <br> <br> The 0th entry in stack represents + * the type of the bottom of the stack, and subsequent entries represent types + * of stack elements closer to the top of the operand stack. We shall refer to + * the bottom element of the stack as stack element 0, and to subsequent + * elements as stack element 1, 2 etc. If stack[M] represents stack element N, + * then stack[M+1] represents stack element N+1 if stack[M] is one of + * Top_variable_info, Integer_variable_info, Float_variable_info, + * Null_variable_info, UninitializedThis_variable_info, Object_variable_info, or + * Uninitialized_variable_info, otherwise stack[M+1] represents stack element + * N+2. It is an error if, for any index i, stack[i] represents a stack entry + * whose index is greater than the maximum operand stack size for the method. + * <br> <br> We say that an instruction in the byte code has a corresponding + * stack map frame if the offset in the offset field of the stack map frame is + * the same as the offset of the instruction in the byte codes. <br> <br> The + * verification_type_info structure consists of a one-byte tag followed by zero + * or more bytes, giving more information about the tag. Each + * verification_type_info structure specifies the verification type of one or + * two locations. + * + * <pre> + * union verification_type_info { + * Top_variable_info; + * Integer_variable_info; + * Float_variable_info; + * Long_variable_info; + * Double_variable_info; + * Null_variable_info; + * UninitializedThis_variable_info; + * Object_variable_info; + * Uninitialized_variable_info; + * } + * </pre> + * + * The Top_variable_info type indicates that the local variable has the + * verification type top (T.) + * + * <pre> + * Top_variable_info { + * u1 tag = ITEM_Top; // 0 + * } + * </pre> + * + * The Integer_variable_info type indicates that the location contains the + * verification type int. + * + * <pre> + * Integer_variable_info { + * u1 tag = ITEM_Integer; // 1 + * } + * </pre> + * + * The Float_variable_info type indicates that the location contains the + * verification type float. + * + * <pre> + * Float_variable_info { + * u1 tag = ITEM_Float; // 2 + * } + * </pre> + * + * The Long_variable_info type indicates that the location contains the + * verification type long. If the location is a local variable, then: + * + * <ul> <li>It must not be the local variable with the highest index.</li> + * <li>The next higher numbered local variable contains the verification type + * T.</li> </ul> + * + * If the location is an operand stack entry, then: + * + * <ul> <li>The current location must not be the topmost location of the + * operand stack.</li> <li>the next location closer to the top of the operand + * stack contains the verification type T.</li> </ul> + * + * This structure gives the contents of two locations in the operand stack or in + * the local variables. + * + * <pre> + * Long_variable_info { + * u1 tag = ITEM_Long; // 4 + * } + * </pre> + * + * The Double_variable_info type indicates that the location contains the + * verification type double. If the location is a local variable, then: + * + * <ul> <li>It must not be the local variable with the highest index.</li> + * <li>The next higher numbered local variable contains the verification type + * T. <li> </ul> + * + * If the location is an operand stack entry, then: + * + * <ul> <li>The current location must not be the topmost location of the + * operand stack.</li> <li>the next location closer to the top of the operand + * stack contains the verification type T.</li> </ul> + * + * This structure gives the contents of two locations in in the operand stack or + * in the local variables. + * + * <pre> + * Double_variable_info { + * u1 tag = ITEM_Double; // 3 + * } + * </pre> + * + * The Null_variable_info type indicates that location contains the verification + * type null. + * + * <pre> + * Null_variable_info { + * u1 tag = ITEM_Null; // 5 + * } + * </pre> + * + * The UninitializedThis_variable_info type indicates that the location contains + * the verification type uninitializedThis. + * + * <pre> + * UninitializedThis_variable_info { + * u1 tag = ITEM_UninitializedThis; // 6 + * } + * </pre> + * + * The Object_variable_info type indicates that the location contains an + * instance of the class referenced by the constant pool entry. + * + * <pre> + * Object_variable_info { + * u1 tag = ITEM_Object; // 7 + * u2 cpool_index; + * } + * </pre> + * + * The Uninitialized_variable_info indicates that the location contains the + * verification type uninitialized(offset). The offset item indicates the offset + * of the new instruction that created the object being stored in the location. + * + * <pre> + * Uninitialized_variable_info { + * u1 tag = ITEM_Uninitialized // 8 + * uoffset offset; + * } + * </pre> + * + * @see "ClassFileFormat-Java6.fm Page 138 Friday, April 15, 2005 3:22 PM" + * + * @author Eugene Kuleshov + */ +public class StackMapTableAttribute extends Attribute { + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is zero. + */ + public static final int SAME_FRAME = 0; // to 63 (0-3f) + + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is 1 + */ + public static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 + + // (40-7f) + + /** + * Reserved for future use + */ + public static final int RESERVED = 128; + + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is 1. Offset is bigger then 63; + */ + public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7 + + /** + * Frame where current locals are the same as the locals in the previous + * frame, except that the k last locals are absent. The value of k is given + * by the formula 251-frame_type. + */ + public static final int CHOP_FRAME = 248; // to 250 (f8-fA) + + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is zero. Offset is bigger then 63; + */ + public static final int SAME_FRAME_EXTENDED = 251; // fb + + /** + * Frame where current locals are the same as the locals in the previous + * frame, except that k additional locals are defined. The value of k is + * given by the formula frame_type-251. + */ + public static final int APPEND_FRAME = 252; // to 254 // fc-fe + + /** + * Full frame + */ + public static final int FULL_FRAME = 255; // ff + + private static final int MAX_SHORT = 65535; + + /** + * A <code>List</code> of <code>StackMapFrame</code> instances. + */ + private List frames; + + public StackMapTableAttribute() { + super("StackMapTable"); + } + + public StackMapTableAttribute(List frames) { + this(); + this.frames = frames; + } + + public List getFrames() { + return frames; + } + + public StackMapFrame getFrame(Label label) { + for (int i = 0; i < frames.size(); i++) { + StackMapFrame frame = (StackMapFrame) frames.get(i); + if (frame.label == label) { + return frame; + } + } + return null; + } + + public boolean isUnknown() { + return false; + } + + public boolean isCodeAttribute() { + return true; + } + + protected Attribute read( + ClassReader cr, + int off, + int len, + char[] buf, + int codeOff, + Label[] labels) + { + + ArrayList frames = new ArrayList(); + + // note that this is not the size of Code attribute + boolean isExtCodeSize = cr.readInt(codeOff + 4) > MAX_SHORT; + boolean isExtLocals = cr.readUnsignedShort(codeOff + 2) > MAX_SHORT; + boolean isExtStack = cr.readUnsignedShort(codeOff) > MAX_SHORT; + + int offset = 0; + + int methodOff = getMethodOff(cr, codeOff, buf); + StackMapFrame frame = new StackMapFrame(getLabel(offset, labels), + calculateLocals(cr.readClass(cr.header + 2, buf), // owner + cr.readUnsignedShort(methodOff), // method access + cr.readUTF8(methodOff + 2, buf), // method name + cr.readUTF8(methodOff + 4, buf)), // method desc + Collections.EMPTY_LIST); + frames.add(frame); + + // System.err.println( cr.readUTF8( methodOff + 2, buf)); + // System.err.println( offset +" delta:" + 0 +" : "+ frame); + + int size; + if (isExtCodeSize) { + size = cr.readInt(off); + off += 4; + } else { + size = cr.readUnsignedShort(off); + off += 2; + } + + for (; size > 0; size--) { + int tag = cr.readByte(off); // & 0xff; + off++; + + List stack; + List locals; + + int offsetDelta; + if (tag < SAME_LOCALS_1_STACK_ITEM_FRAME) { // SAME_FRAME + offsetDelta = tag; + + locals = new ArrayList(frame.locals); + stack = Collections.EMPTY_LIST; + + } else if (tag < RESERVED) { // SAME_LOCALS_1_STACK_ITEM_FRAME + offsetDelta = tag - SAME_LOCALS_1_STACK_ITEM_FRAME; + + locals = new ArrayList(frame.locals); + stack = new ArrayList(); + // read verification_type_info stack[1]; + off = readType(stack, isExtCodeSize, cr, off, labels, buf); + + } else { + if (isExtCodeSize) { + offsetDelta = cr.readInt(off); + off += 4; + } else { + offsetDelta = cr.readUnsignedShort(off); + off += 2; + } + + if (tag == SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { // SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED + locals = new ArrayList(frame.locals); + stack = new ArrayList(); + // read verification_type_info stack[1]; + off = readType(stack, isExtCodeSize, cr, off, labels, buf); + + } else if (tag >= CHOP_FRAME && tag < SAME_FRAME_EXTENDED) { // CHOP_FRAME + stack = Collections.EMPTY_LIST; + + int k = SAME_FRAME_EXTENDED - tag; + // copy locals from prev frame and chop last k + locals = new ArrayList(frame.locals.subList(0, + frame.locals.size() - k)); + + } else if (tag == SAME_FRAME_EXTENDED) { // SAME_FRAME_EXTENDED + stack = Collections.EMPTY_LIST; + locals = new ArrayList(frame.locals); + + } else if ( /* tag>=APPEND && */tag < FULL_FRAME) { // APPEND_FRAME + stack = Collections.EMPTY_LIST; + + // copy locals from prev frame and append new k + locals = new ArrayList(frame.locals); + for (int k = tag - SAME_FRAME_EXTENDED; k > 0; k--) { + off = readType(locals, + isExtCodeSize, + cr, + off, + labels, + buf); + } + + } else if (tag == FULL_FRAME) { // FULL_FRAME + // read verification_type_info locals[number_of_locals]; + locals = new ArrayList(); + off = readTypes(locals, + isExtLocals, + isExtCodeSize, + cr, + off, + labels, + buf); + + // read verification_type_info stack[number_of_stack_items]; + stack = new ArrayList(); + off = readTypes(stack, + isExtStack, + isExtCodeSize, + cr, + off, + labels, + buf); + + } else { + throw new RuntimeException("Unknown frame type " + tag + + " after offset " + offset); + + } + } + + offset += offsetDelta; + + Label offsetLabel = getLabel(offset, labels); + + frame = new StackMapFrame(offsetLabel, locals, stack); + frames.add(frame); + // System.err.println( tag +" " + offset +" delta:" + offsetDelta + + // " frameType:"+ frameType+" : "+ frame); + + offset++; + } + + return new StackMapTableAttribute(frames); + } + + protected ByteVector write( + ClassWriter cw, + byte[] code, + int len, + int maxStack, + int maxLocals) + { + ByteVector bv = new ByteVector(); + // TODO verify this value (MAX_SHORT) + boolean isExtCodeSize = code != null && code.length > MAX_SHORT; + writeSize(frames.size() - 1, bv, isExtCodeSize); + + if (frames.size() < 2) { + return bv; + } + + boolean isExtLocals = maxLocals > MAX_SHORT; + boolean isExtStack = maxStack > MAX_SHORT; + + // skip the first frame + StackMapFrame frame = (StackMapFrame) frames.get(0); + List locals = frame.locals; + int offset = frame.label.getOffset(); + + for (int i = 1; i < frames.size(); i++) { + frame = (StackMapFrame) frames.get(i); + + List clocals = frame.locals; + List cstack = frame.stack; + int coffset = frame.label.getOffset(); + + int clocalsSize = clocals.size(); + int cstackSize = cstack.size(); + + int localsSize = locals.size(); + + int delta = coffset - offset; + + int type = FULL_FRAME; + int k = 0; + if (cstackSize == 0) { + k = clocalsSize - localsSize; + switch (k) { + case -3: + case -2: + case -1: + type = CHOP_FRAME; // CHOP or FULL + localsSize = clocalsSize; // for full_frame check + break; + + case 0: + // SAME, SAME_EXTENDED or FULL + type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED; + break; + + case 1: + case 2: + case 3: + type = APPEND_FRAME; // APPEND or FULL + break; + } + } else if (localsSize == clocalsSize && cstackSize == 1) { + // SAME_LOCAL_1_STACK or FULL + type = delta < 63 + ? SAME_LOCALS_1_STACK_ITEM_FRAME + : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED; + } + + if (type != FULL_FRAME) { + // verify if stack and locals are the same + for (int j = 0; j < localsSize && type != FULL_FRAME; j++) { + if (!locals.get(j).equals(clocals.get(j))) + type = FULL_FRAME; + } + } + + switch (type) { + case SAME_FRAME: + bv.putByte(delta); + break; + + case SAME_LOCALS_1_STACK_ITEM_FRAME: + bv.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); + writeTypeInfos(bv, cw, cstack, 0, 1); + break; + + case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED: + bv.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED); + writeSize(delta, bv, isExtCodeSize); + writeTypeInfos(bv, cw, cstack, 0, 1); + break; + + case SAME_FRAME_EXTENDED: + bv.putByte(SAME_FRAME_EXTENDED); + writeSize(delta, bv, isExtCodeSize); + break; + + case CHOP_FRAME: + bv.putByte(SAME_FRAME_EXTENDED + k); // negative k + writeSize(delta, bv, isExtCodeSize); + break; + + case APPEND_FRAME: + bv.putByte(SAME_FRAME_EXTENDED + k); // positive k + writeSize(delta, bv, isExtCodeSize); + writeTypeInfos(bv, + cw, + clocals, + clocalsSize - 1, + clocalsSize); + break; + + case FULL_FRAME: + bv.putByte(FULL_FRAME); + writeSize(delta, bv, isExtCodeSize); + writeSize(clocalsSize, bv, isExtLocals); + writeTypeInfos(bv, cw, clocals, 0, clocalsSize); + writeSize(cstackSize, bv, isExtStack); + writeTypeInfos(bv, cw, cstack, 0, cstackSize); + break; + + default: + throw new RuntimeException(); + } + offset = coffset + 1; // compensating non first offset + locals = clocals; + } + return bv; + } + + private void writeSize(int delta, ByteVector bv, boolean isExt) { + if (isExt) { + bv.putInt(delta); + } else { + bv.putShort(delta); + } + } + + private void writeTypeInfos( + ByteVector bv, + ClassWriter cw, + List info, + int start, + int end) + { + for (int j = start; j < end; j++) { + StackMapType typeInfo = (StackMapType) info.get(j); + bv.putByte(typeInfo.getType()); + + switch (typeInfo.getType()) { + case StackMapType.ITEM_Object: // + bv.putShort(cw.newClass(typeInfo.getObject())); + break; + + case StackMapType.ITEM_Uninitialized: // + bv.putShort(typeInfo.getLabel().getOffset()); + break; + + } + } + } + + public static int getMethodOff(ClassReader cr, int codeOff, char[] buf) { + int off = cr.header + 6; + + int interfacesCount = cr.readUnsignedShort(off); + off += 2 + interfacesCount * 2; + + int fieldsCount = cr.readUnsignedShort(off); + off += 2; + for (; fieldsCount > 0; --fieldsCount) { + int attrCount = cr.readUnsignedShort(off + 6); // field attributes + off += 8; + for (; attrCount > 0; --attrCount) { + off += 6 + cr.readInt(off + 2); + } + } + + int methodsCount = cr.readUnsignedShort(off); + off += 2; + for (; methodsCount > 0; --methodsCount) { + int methodOff = off; + int attrCount = cr.readUnsignedShort(off + 6); // method attributes + off += 8; + for (; attrCount > 0; --attrCount) { + String attrName = cr.readUTF8(off, buf); + off += 6; + if (attrName.equals("Code")) { + if (codeOff == off) { + return methodOff; + } + } + off += cr.readInt(off - 4); + } + } + + return -1; + } + + /** + * Use method signature and access flags to resolve initial locals state. + * + * @param className name of the method's owner class. + * @param access access flags of the method. + * @param methodName name of the method. + * @param methodDesc descriptor of the method. + * @return list of <code>StackMapType</code> instances representing locals + * for an initial frame. + */ + public static List calculateLocals( + String className, + int access, + String methodName, + String methodDesc) + { + List locals = new ArrayList(); + + // TODO + if ("<init>".equals(methodName) + && !className.equals("java/lang/Object")) + { + StackMapType typeInfo = StackMapType.getTypeInfo(StackMapType.ITEM_UninitializedThis); + typeInfo.setObject(className); // this + locals.add(typeInfo); + } else if ((access & Opcodes.ACC_STATIC) == 0) { + StackMapType typeInfo = StackMapType.getTypeInfo(StackMapType.ITEM_Object); + typeInfo.setObject(className); // this + locals.add(typeInfo); + } + + Type[] types = Type.getArgumentTypes(methodDesc); + for (int i = 0; i < types.length; i++) { + Type t = types[i]; + StackMapType smt; + switch (t.getSort()) { + case Type.LONG: + smt = StackMapType.getTypeInfo(StackMapType.ITEM_Long); + break; + case Type.DOUBLE: + smt = StackMapType.getTypeInfo(StackMapType.ITEM_Double); + break; + + case Type.FLOAT: + smt = StackMapType.getTypeInfo(StackMapType.ITEM_Float); + break; + + case Type.ARRAY: + case Type.OBJECT: + smt = StackMapType.getTypeInfo(StackMapType.ITEM_Object); + smt.setObject(t.getDescriptor()); // TODO verify name + break; + + default: + smt = StackMapType.getTypeInfo(StackMapType.ITEM_Integer); + break; + } + } + + return locals; + } + + private int readTypes( + List info, + boolean isExt, + boolean isExtCodeSize, + ClassReader cr, + int off, + Label[] labels, + char[] buf) + { + int n = 0; + if (isExt) { + n = cr.readInt(off); + off += 4; + } else { + n = cr.readUnsignedShort(off); + off += 2; + } + + for (; n > 0; n--) { + off = readType(info, isExtCodeSize, cr, off, labels, buf); + } + return off; + } + + private int readType( + List info, + boolean isExtCodeSize, + ClassReader cr, + int off, + Label[] labels, + char[] buf) + { + int itemType = cr.readByte(off++); + StackMapType typeInfo = StackMapType.getTypeInfo(itemType); + info.add(typeInfo); + switch (itemType) { + // case StackMapType.ITEM_Long: // + // case StackMapType.ITEM_Double: // + // info.add(StackMapType.getTypeInfo(StackMapType.ITEM_Top)); + // break; + + case StackMapType.ITEM_Object: // + typeInfo.setObject(cr.readClass(off, buf)); + off += 2; + break; + + case StackMapType.ITEM_Uninitialized: // + int offset; + if (isExtCodeSize) { + offset = cr.readInt(off); + off += 4; + } else { + offset = cr.readUnsignedShort(off); + off += 2; + } + + typeInfo.setLabel(getLabel(offset, labels)); + break; + } + return off; + } + + private Label getLabel(int offset, Label[] labels) { + Label l = labels[offset]; + if (l != null) { + return l; + } + return labels[offset] = new Label(); + } + + public String toString() { + StringBuffer sb = new StringBuffer("StackMapTable["); + for (int i = 0; i < frames.size(); i++) { + sb.append('\n').append('[').append(frames.get(i)).append(']'); + } + sb.append("\n]"); + return sb.toString(); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapType.java =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapType.java (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/attrs/StackMapType.java 2007-01-07 13:36:55 UTC (rev 3028) @@ -0,0 +1,114 @@ +/** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.objectweb.asm.attrs; + +import org.objectweb.asm.Label; + +/** + * Verification type info used by {@link StackMapAttribute}. + * + * @see <a href="http://www.jcp.org/en/jsr/detail?id=139">JSR 139 : Connected + * Limited Device Configuration 1.1</a> + * + * @see "ClassFileFormat-Java6.fm Page 138 Friday, April 15, 2005 3:22 PM" + * + * @author Eugene Kuleshov + */ + +public class StackMapType { + + public static final int ITEM_Top = 0; + public static final int ITEM_Integer = 1; + public static final int ITEM_Float = 2; + public static final int ITEM_Double = 3; + public static final int ITEM_Long = 4; + public static final int ITEM_Null = 5; + public static final int ITEM_UninitializedThis = 6; + public static final int ITEM_Object = 7; + public static final int ITEM_Uninitialized = 8; + + public static final String[] ITEM_NAMES = { + "Top", + "Integer", + "Float", + "Double", + "Long", + "Null", + "UninitializedThis", + "Object", + "Uninitialized" }; + + private int type; + private Label offset; + private String object; + + private StackMapType(int type) { + this.type = type; + } + + public int getType() { + return type; + } + + public static StackMapType getTypeInfo(int itemType) { + if (itemType < ITEM_Top || itemType > ITEM_Uninitialized) { + throw new IllegalArgumentException("" + itemType); + } + return new StackMapType(itemType); + } + + public void setLabel(Label offset) { + this.offset = offset; + } + + public void setObject(String object) { + this.object = object; + } + + public Label getLabel() { + return offset; + } + + public String getObject() { + return object; + } + + public String toString() { + StringBuffer sb = new StringBuffer(ITEM_NAMES[type]); + if (type == ITEM_Object) { + sb.append(":").append(object); + } + if (type == ITEM_Uninitialized) { + sb.append(":L").append(System.identityHashCode(offset)); + } + return sb.toString(); + } +} Added: trunk/core/src/classpath/org/org/objectweb/asm/attrs/package.html =================================================================== --- trunk/core/src/classpath/org/org/objectweb/asm/attrs/package.html (rev 0) +++ trunk/core/src/classpath/org/org/objectweb/asm/attrs/package.html 2007-01-07 13:36:55 UTC (rev 3028) @@ -0,0 +1,48 @@ +<html> +<!-- + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2005 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. +--> +<body> +Provides an implementation for optional class, field and method attributes. + +<p> + +By default ASM strips optional attributes, in order to keep them in +the bytecode that is being readed you should pass an array of required attribute +instances to {@link org.objectweb.asm.ClassReader#accept(org.objectweb.asm.ClassVisitor, org.objectweb.asm.Attribute[], boolean) ClassReader.accept()} method. +In order to add custom attributes to the manually constructed bytecode concrete +subclasses of the {@link org.objectweb.asm.Attribute Attribute} can be passed to +the visitAttribute methods of the +{@link org.objectweb.asm.ClassVisitor ClassVisitor}, +{@link org.objectweb.asm.FieldVisitor FieldVisitor} and +{@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces. + +@since ASM 1.4.1 +</body> +</html> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-07 13:28:26
|
Revision: 3027 http://jnode.svn.sourceforge.net/jnode/?rev=3027&view=rev Author: lsantha Date: 2007-01-07 05:28:25 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Added Paths: ----------- trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/ trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/AbstractMethodGenerator.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/ClassRmicCompiler.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/CompilationError.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/Generator.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/GiopIo.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/HashFinder.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/Main.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/Messages.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/MethodGenerator.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/RMICException.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/RmiMethodGenerator.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/RmicBackend.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/SourceGiopRmicCompiler.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/SourceRmicCompiler.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/Variables.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/WrapUnWrapper.java trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/messages.properties trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/templates/ trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/templates/ImplTie.jav trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/templates/Stub.jav trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/templates/StubMethod.jav trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/templates/StubMethodVoid.jav trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/templates/Stub_12.jav trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/templates/Stub_12Method.jav trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/templates/Stub_12MethodVoid.jav trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/templates/Tie.jav trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/templates/TieMethod.jav trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/templates/TieMethodVoid.jav Added: trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/AbstractMethodGenerator.java =================================================================== --- trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/AbstractMethodGenerator.java (rev 0) +++ trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/AbstractMethodGenerator.java 2007-01-07 13:28:25 UTC (rev 3027) @@ -0,0 +1,53 @@ +/* AbstractMethodGenerator.java -- the abstract method generator + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.classpath.tools.rmic; + +public interface AbstractMethodGenerator +{ + /** + * Generate this method for the Stub (remote caller) class. + */ + String generateStubMethod(); + + /** + * Generate this method for the Tie (remote servant) class. + */ + String generateTieMethod(); + +} Added: trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/ClassRmicCompiler.java =================================================================== --- trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/ClassRmicCompiler.java (rev 0) +++ trunk/core/src/classpath/tools/gnu/classpath/tools/rmic/ClassRmicCompiler.java 2007-01-07 13:28:25 UTC (rev 3027) @@ -0,0 +1,1824 @@ +/* ClassRmicCompiler.java -- + Copyright (c) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. */ + +package gnu.classpath.tools.rmic; + +import gnu.java.rmi.server.RMIHashes; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.PrintWriter; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.rmi.MarshalException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.UnexpectedException; +import java.rmi.UnmarshalException; +import java.rmi.server.Operation; +import java.rmi.server.RemoteCall; +import java.rmi.server.RemoteObject; +import java.rmi.server.RemoteRef; +import java.rmi.server.RemoteStub; +import java.rmi.server.Skeleton; +import java.rmi.server.SkeletonMismatchException; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.StringTokenizer; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; + +public class ClassRmicCompiler + implements RmicBackend +{ + private String[] args; + private int next; + private List errors = new ArrayList(); + private boolean keep = false; + private boolean need11Stubs = true; + private boolean need12Stubs = true; + private boolean compile = true; + private boolean verbose; + private boolean noWrite; + private String destination; + private String classpath; + private ClassLoader loader; + private int errorCount = 0; + + private Class clazz; + private String classname; + private String classInternalName; + private String fullclassname; + private MethodRef[] remotemethods; + private String stubname; + private String skelname; + private List mRemoteInterfaces; + + /** + * @return true if run was successful + */ + public boolean run(String[] inputFiles) + { + args = inputFiles; + + if (next >= args.length) + return false; + + for (int i = next; i < args.length; i++) + { + try + { + if (verbose) + System.out.println("[Processing class " + args[i] + ".class]"); + processClass(args[i].replace(File.separatorChar, '.')); + } + catch (IOException e) + { + errors.add(e); + } + catch (RMICException e) + { + errors.add(e); + } + } + if (errors.size() > 0) + { + for (Iterator it = errors.iterator(); it.hasNext(); ) + { + Exception ex = (Exception) it.next(); + logError(ex); + } + } + + return errorCount == 0; + } + + private void processClass(String cls) throws IOException, RMICException + { + // reset class specific vars + clazz = null; + classname = null; + classInternalName = null; + fullclassname = null; + remotemethods = null; + stubname = null; + skelname = null; + mRemoteInterfaces = new ArrayList(); + + analyzeClass(cls); + generateStub(); + if (need11Stubs) + generateSkel(); + } + + private void analyzeClass(String cname) + throws RMICException + { + if (verbose) + System.out.println("[analyze class " + cname + "]"); + int p = cname.lastIndexOf('.'); + if (p != -1) + classname = cname.substring(p + 1); + else + classname = cname; + fullclassname = cname; + + findClass(); + findRemoteMethods(); + } + + /** + * @deprecated + */ + public Exception getException() + { + return errors.size() == 0 ? null : (Exception) errors.get(0); + } + + private void findClass() + throws RMICException + { + ClassLoader cl = (loader == null + ? ClassLoader.getSystemClassLoader() + : loader); + try + { + clazz = Class.forName(fullclassname, false, cl); + } + catch (ClassNotFoundException cnfe) + { + throw new RMICException + ("Class " + fullclassname + " not found in classpath", cnfe); + } + + if (! Remote.class.isAssignableFrom(clazz)) + { + throw new RMICException + ("Class " + clazz.getName() + + " does not implement a remote interface."); + } + } + + private static Type[] typeArray(Class[] cls) + { + Type[] t = new Type[cls.length]; + for (int i = 0; i < cls.length; i++) + { + t[i] = Type.getType(cls[i]); + } + + return t; + } + + private static String[] internalNameArray(Type[] t) + { + String[] s = new String[t.length]; + for (int i = 0; i < t.length; i++) + { + s[i] = t[i].getInternalName(); + } + + return s; + } + + private static String[] internalNameArray(Class[] c) + { + return internalNameArray(typeArray(c)); + } + + private static final String forName = "class$"; + + private static Object param(Method m, int argIndex) + { + List l = new ArrayList(); + l.add(m); + l.add(new Integer(argIndex)); + return l; + } + + private static void generateClassForNamer(ClassVisitor cls) + { + MethodVisitor cv = + cls.visitMethod + (Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC + Opcodes.ACC_SYNTHETIC, forName, + Type.getMethodDescriptor + (Type.getType(Class.class), new Type[] { Type.getType(String.class) }), + null, null); + + Label start = new Label(); + cv.visitLabel(start); + cv.visitVarInsn(Opcodes.ALOAD, 0); + cv.visitMethodInsn + (Opcodes.INVOKESTATIC, + Type.getInternalName(Class.class), + "forName", + Type.getMethodDescriptor + (Type.getType(Class.class), new Type[] { Type.getType(String.class) })); + cv.visitInsn(Opcodes.ARETURN); + + Label handler = new Label(); + cv.visitLabel(handler); + cv.visitVarInsn(Opcodes.ASTORE, 1); + cv.visitTypeInsn(Opcodes.NEW, typeArg(NoClassDefFoundError.class)); + cv.visitInsn(Opcodes.DUP); + cv.visitVarInsn(Opcodes.ALOAD, 1); + cv.visitMethodInsn + (Opcodes.INVOKEVIRTUAL, + Type.getInternalName(ClassNotFoundException.class), + "getMessage", + Type.getMethodDescriptor(Type.getType(String.class), new Type[] {})); + cv.visitMethodInsn + (Opcodes.INVOKESPECIAL, + Type.getInternalName(NoClassDefFoundError.class), + "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, new Type[] { Type.getType(String.class) })); + cv.visitInsn(Opcodes.ATHROW); + cv.visitTryCatchBlock + (start, handler, handler, + Type.getInternalName(ClassNotFoundException.class)); + cv.visitMaxs(-1, -1); + } + + private void generateClassConstant(MethodVisitor cv, Class cls) { + if (cls.isPrimitive()) + { + Class boxCls; + if (cls.equals(Boolean.TYPE)) + boxCls = Boolean.class; + else if (cls.equals(Character.TYPE)) + boxCls = Character.class; + else if (cls.equals(Byte.TYPE)) + boxCls = Byte.class; + else if (cls.equals(Short.TYPE)) + boxCls = Short.class; + else if (cls.equals(Integer.TYPE)) + boxCls = Integer.class; + else if (cls.equals(Long.TYPE)) + boxCls = Long.class; + else if (cls.equals(Float.TYPE)) + boxCls = Float.class; + else if (cls.equals(Double.TYPE)) + boxCls = Double.class; + else if (cls.equals(Void.TYPE)) + boxCls = Void.class; + else + throw new IllegalArgumentException("unknown primitive type " + cls); + + cv.visitFieldInsn + (Opcodes.GETSTATIC, Type.getInternalName(boxCls), "TYPE", + Type.getDescriptor(Class.class)); + return; + } + cv.visitLdcInsn(cls.getName()); + cv.visitMethodInsn + (Opcodes.INVOKESTATIC, classInternalName, forName, + Type.getMethodDescriptor + (Type.getType(Class.class), + new Type[] { Type.getType(String.class) })); + } + + private void generateClassArray(MethodVisitor code, Class[] classes) + { + code.visitLdcInsn(new Integer(classes.length)); + code.visitTypeInsn(Opcodes.ANEWARRAY, typeArg(Class.class)); + for (int i = 0; i < classes.length; i++) + { + code.visitInsn(Opcodes.DUP); + code.visitLdcInsn(new Integer(i)); + generateClassConstant(code, classes[i]); + code.visitInsn(Opcodes.AASTORE); + } + } + + private void fillOperationArray(MethodVisitor clinit) + { + // Operations array + clinit.visitLdcInsn(new Integer(remotemethods.length)); + clinit.visitTypeInsn(Opcodes.ANEWARRAY, typeArg(Operation.class)); + clinit.visitFieldInsn + (Opcodes.PUTSTATIC, classInternalName, "operations", + Type.getDescriptor(Operation[].class)); + + for (int i = 0; i < remotemethods.length; i++) + { + Method m = remotemethods[i].meth; + + StringBuffer desc = new StringBuffer(); + desc.append(getPrettyName(m.getReturnType()) + " "); + desc.append(m.getName() + "("); + + // signature + Class[] sig = m.getParameterTypes(); + for (int j = 0; j < sig.length; j++) + { + desc.append(getPrettyName(sig[j])); + if (j + 1 < sig.length) + desc.append(", "); + } + + // push operations array + clinit.visitFieldInsn + (Opcodes.GETSTATIC, classInternalName, "operations", + Type.getDescriptor(Operation[].class)); + + // push array index + clinit.visitLdcInsn(new Integer(i)); + + // instantiate operation and leave a copy on the stack + clinit.visitTypeInsn(Opcodes.NEW, typeArg(Operation.class)); + clinit.visitInsn(Opcodes.DUP); + clinit.visitLdcInsn(desc.toString()); + clinit.visitMethodInsn + (Opcodes.INVOKESPECIAL, + Type.getInternalName(Operation.class), + "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, new Type[] { Type.getType(String.class) })); + + // store in operations array + clinit.visitInsn(Opcodes.AASTORE); + } + } + + private void generateStaticMethodObjs(MethodVisitor clinit) + { + for (int i = 0; i < remotemethods.length; i++) + { + Method m = remotemethods[i].meth; + + /* + * $method_<i>m.getName()</i>_<i>i</i> = + * <i>m.getDeclaringClass()</i>.class.getMethod + * (m.getName(), m.getParameterType()) + */ + String methodVar = "$method_" + m.getName() + "_" + i; + generateClassConstant(clinit, m.getDeclaringClass()); + clinit.visitLdcInsn(m.getName()); + generateClassArray(clinit, m.getParameterTypes()); + clinit.visitMethodInsn + (Opcodes.INVOKEVIRTUAL, + Type.getInternalName(Class.class), + "getMethod", + Type.getMethodDescriptor + (Type.getType(Method.class), + new Type[] { Type.getType(String.class), + Type.getType(Class[].class) })); + + clinit.visitFieldInsn + (Opcodes.PUTSTATIC, classInternalName, methodVar, + Type.getDescriptor(Method.class)); + } + } + + private void generateStub() + throws IOException + { + stubname = fullclassname + "_Stub"; + String stubclassname = classname + "_Stub"; + File file = new File((destination == null ? "." : destination) + + File.separator + + stubname.replace('.', File.separatorChar) + + ".class"); + + if (verbose) + System.out.println("[Generating class " + stubname + "]"); + + final ClassWriter stub = new ClassWriter(true); + classInternalName = stubname.replace('.', '/'); + final String superInternalName = + Type.getType(RemoteStub.class).getInternalName(); + + String[] remoteInternalNames = + internalNameArray((Class[]) mRemoteInterfaces.toArray(new Class[] {})); + stub.visit + (Opcodes.V1_2, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, classInternalName, + null, superInternalName, remoteInternalNames); + + if (need12Stubs) + { + stub.visitField + (Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL, "serialVersionUID", + Type.LONG_TYPE.getDescriptor(), null, new Long(2L)); + } + + if (need11Stubs) + { + stub.visitField + (Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL, + "interfaceHash", Type.LONG_TYPE.getDescriptor(), null, + new Long(RMIHashes.getInterfaceHash(clazz))); + + if (need12Stubs) + { + stub.visitField + (Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, "useNewInvoke", + Type.BOOLEAN_TYPE.getDescriptor(), null, null); + } + + stub.visitField + (Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL, + "operations", Type.getDescriptor(Operation[].class), null, null); + } + + // Set of method references. + if (need12Stubs) + { + for (int i = 0; i < remotemethods.length; i++) + { + Method m = remotemethods[i].meth; + String slotName = "$method_" + m.getName() + "_" + i; + stub.visitField + (Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, slotName, + Type.getDescriptor(Method.class), null, null); + } + } + + MethodVisitor clinit = stub.visitMethod + (Opcodes.ACC_STATIC, "<clinit>", + Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}), null, null); + + if (need11Stubs) + { + fillOperationArray(clinit); + if (! need12Stubs) + clinit.visitInsn(Opcodes.RETURN); + } + + if (need12Stubs) + { + // begin of try + Label begin = new Label(); + + // beginning of catch + Label handler = new Label(); + clinit.visitLabel(begin); + + // Initialize the methods references. + if (need11Stubs) + { + /* + * RemoteRef.class.getMethod("invoke", new Class[] { + * Remote.class, Method.class, Object[].class, long.class }) + */ + generateClassConstant(clinit, RemoteRef.class); + clinit.visitLdcInsn("invoke"); + generateClassArray + (clinit, new Class[] { Remote.class, Method.class, + Object[].class, long.class }); + clinit.visitMethodInsn + (Opcodes.INVOKEVIRTUAL, + Type.getInternalName(Class.class), + "getMethod", + Type.getMethodDescriptor + (Type.getType(Method.class), + new Type[] { Type.getType(String.class), + Type.getType(Class[].class) })); + + // useNewInvoke = true + clinit.visitInsn(Opcodes.ICONST_1); + clinit.visitFieldInsn + (Opcodes.PUTSTATIC, classInternalName, "useNewInvoke", + Type.BOOLEAN_TYPE.getDescriptor()); + } + + generateStaticMethodObjs(clinit); + + // jump past handler + clinit.visitInsn(Opcodes.RETURN); + clinit.visitLabel(handler); + if (need11Stubs) + { + // useNewInvoke = false + clinit.visitInsn(Opcodes.ICONST_0); + clinit.visitFieldInsn + (Opcodes.PUTSTATIC, classInternalName, "useNewInvoke", + Type.BOOLEAN_TYPE.getDescriptor()); + clinit.visitInsn(Opcodes.RETURN); + } + else + { + // throw NoSuchMethodError + clinit.visitTypeInsn(Opcodes.NEW, typeArg(NoSuchMethodError.class)); + clinit.visitInsn(Opcodes.DUP); + clinit.visitLdcInsn("stub class initialization failed"); + clinit.visitMethodInsn + (Opcodes.INVOKESPECIAL, + Type.getInternalName(NoSuchMethodError.class), + "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, + new Type[] { Type.getType(String.class) })); + clinit.visitInsn(Opcodes.ATHROW); + } + + clinit.visitTryCatchBlock + (begin, handler, handler, + Type.getInternalName(NoSuchMethodException.class)); + + } + + clinit.visitMaxs(-1, -1); + + generateClassForNamer(stub); + + // Constructors + if (need11Stubs) + { + // no arg public constructor + MethodVisitor code = stub.visitMethod + (Opcodes.ACC_PUBLIC, "<init>", + Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}), + null, null); + code.visitVarInsn(Opcodes.ALOAD, 0); + code.visitMethodInsn + (Opcodes.INVOKESPECIAL, superInternalName, "<init>", + Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {})); + code.visitInsn(Opcodes.RETURN); + + code.visitMaxs(-1, -1); + } + + // public RemoteRef constructor + MethodVisitor constructor = stub.visitMethod + (Opcodes.ACC_PUBLIC, "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, new Type[] {Type.getType(RemoteRef.class)}), + null, null); + constructor.visitVarInsn(Opcodes.ALOAD, 0); + constructor.visitVarInsn(Opcodes.ALOAD, 1); + constructor.visitMethodInsn + (Opcodes.INVOKESPECIAL, superInternalName, "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, new Type[] {Type.getType(RemoteRef.class)})); + constructor.visitInsn(Opcodes.RETURN); + constructor.visitMaxs(-1, -1); + + // Method implementations + for (int i = 0; i < remotemethods.length; i++) + { + Method m = remotemethods[i].meth; + Class[] sig = m.getParameterTypes(); + Class returntype = m.getReturnType(); + Class[] except = sortExceptions + ((Class[]) remotemethods[i].exceptions.toArray(new Class[0])); + + MethodVisitor code = stub.visitMethod + (Opcodes.ACC_PUBLIC, + m.getName(), + Type.getMethodDescriptor(Type.getType(returntype), typeArray(sig)), + null, + internalNameArray(typeArray(except))); + + final Variables var = new Variables(); + + // this and parameters are the declared vars + var.declare("this"); + for (int j = 0; j < sig.length; j++) + var.declare(param(m, j), size(sig[j])); + + Label methodTryBegin = new Label(); + code.visitLabel(methodTryBegin); + + if (need12Stubs) + { + Label oldInvoke = new Label(); + if (need11Stubs) + { + // if not useNewInvoke jump to old invoke + code.visitFieldInsn + (Opcodes.GETSTATIC, classInternalName, "useNewInvoke", + Type.getDescriptor(boolean.class)); + code.visitJumpInsn(Opcodes.IFEQ, oldInvoke); + } + + // this.ref + code.visitVarInsn(Opcodes.ALOAD, var.get("this")); + code.visitFieldInsn + (Opcodes.GETFIELD, Type.getInternalName(RemoteObject.class), + "ref", Type.getDescriptor(RemoteRef.class)); + + // "this" is first arg to invoke + code.visitVarInsn(Opcodes.ALOAD, var.get("this")); + + // method object is second arg to invoke + String methName = "$method_" + m.getName() + "_" + i; + code.visitFieldInsn + (Opcodes.GETSTATIC, classInternalName, methName, + Type.getDescriptor(Method.class)); + + // args to remote method are third arg to invoke + if (sig.length == 0) + code.visitInsn(Opcodes.ACONST_NULL); + else + { + // create arg Object[] (with boxed primitives) and push it + code.visitLdcInsn(new Integer(sig.length)); + code.visitTypeInsn(Opcodes.ANEWARRAY, typeArg(Object.class)); + + var.allocate("argArray"); + code.visitVarInsn(Opcodes.ASTORE, var.get("argArray")); + + for (int j = 0; j < sig.length; j++) + { + int size = size(sig[j]); + int insn = loadOpcode(sig[j]); + Class box = sig[j].isPrimitive() ? box(sig[j]) : null; + + code.visitVarInsn(Opcodes.ALOAD, var.get("argArray")); + code.visitLdcInsn(new Integer(j)); + + // put argument on stack + if (box != null) + { + code.visitTypeInsn(Opcodes.NEW, typeArg(box)); + code.visitInsn(Opcodes.DUP); + code.visitVarInsn(insn, var.get(param(m, j))); + code.visitMethodInsn + (Opcodes.INVOKESPECIAL, + Type.getInternalName(box), + "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, + new Type[] { Type.getType(sig[j]) })); + } + else + code.visitVarInsn(insn, var.get(param(m, j))); + + code.visitInsn(Opcodes.AASTORE); + } + + code.visitVarInsn(Opcodes.ALOAD, var.deallocate("argArray")); + } + + // push remote operation opcode + code.visitLdcInsn(new Long(remotemethods[i].hash)); + code.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(RemoteRef.class), + "invoke", + Type.getMethodDescriptor + (Type.getType(Object.class), + new Type[] { Type.getType(Remote.class), + Type.getType(Method.class), + Type.getType(Object[].class), + Type.LONG_TYPE })); + + if (! returntype.equals(Void.TYPE)) + { + int retcode = returnOpcode(returntype); + Class boxCls = + returntype.isPrimitive() ? box(returntype) : null; + code.visitTypeInsn + (Opcodes.CHECKCAST, typeArg(boxCls == null ? returntype : boxCls)); + if (returntype.isPrimitive()) + { + // unbox + code.visitMethodInsn + (Opcodes.INVOKEVIRTUAL, + Type.getType(boxCls).getInternalName(), + unboxMethod(returntype), + Type.getMethodDescriptor + (Type.getType(returntype), new Type[] {})); + } + + code.visitInsn(retcode); + } + else + code.visitInsn(Opcodes.RETURN); + + + if (need11Stubs) + code.visitLabel(oldInvoke); + } + + if (need11Stubs) + { + + // this.ref.newCall(this, operations, index, interfaceHash) + code.visitVarInsn(Opcodes.ALOAD, var.get("this")); + code.visitFieldInsn + (Opcodes.GETFIELD, + Type.getInternalName(RemoteObject.class), + "ref", + Type.getDescriptor(RemoteRef.class)); + + // "this" is first arg to newCall + code.visitVarInsn(Opcodes.ALOAD, var.get("this")); + + // operations is second arg to newCall + code.visitFieldInsn + (Opcodes.GETSTATIC, classInternalName, "operations", + Type.getDescriptor(Operation[].class)); + + // method index is third arg + code.visitLdcInsn(new Integer(i)); + + // interface hash is fourth arg + code.visitFieldInsn + (Opcodes.GETSTATIC, classInternalName, "interfaceHash", + Type.LONG_TYPE.getDescriptor()); + + code.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(RemoteRef.class), + "newCall", + Type.getMethodDescriptor + (Type.getType(RemoteCall.class), + new Type[] { Type.getType(RemoteObject.class), + Type.getType(Operation[].class), + Type.INT_TYPE, + Type.LONG_TYPE })); + + // store call object on stack and leave copy on stack + var.allocate("call"); + code.visitInsn(Opcodes.DUP); + code.visitVarInsn(Opcodes.ASTORE, var.get("call")); + + Label beginArgumentTryBlock = new Label(); + code.visitLabel(beginArgumentTryBlock); + + // ObjectOutput out = call.getOutputStream(); + code.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(RemoteCall.class), + "getOutputStream", + Type.getMethodDescriptor + (Type.getType(ObjectOutput.class), new Type[] {})); + + for (int j = 0; j < sig.length; j++) + { + // dup the ObjectOutput + code.visitInsn(Opcodes.DUP); + + // get j'th arg to remote method + code.visitVarInsn(loadOpcode(sig[j]), var.get(param(m, j))); + + Class argCls = + sig[j].isPrimitive() ? sig[j] : Object.class; + + // out.writeFoo + code.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(ObjectOutput.class), + writeMethod(sig[j]), + Type.getMethodDescriptor + (Type.VOID_TYPE, + new Type[] { Type.getType(argCls) })); + } + + // pop ObjectOutput + code.visitInsn(Opcodes.POP); + + Label iohandler = new Label(); + Label endArgumentTryBlock = new Label(); + code.visitJumpInsn(Opcodes.GOTO, endArgumentTryBlock); + code.visitLabel(iohandler); + + // throw new MarshalException(msg, ioexception); + code.visitVarInsn(Opcodes.ASTORE, var.allocate("exception")); + code.visitTypeInsn(Opcodes.NEW, typeArg(MarshalException.class)); + code.visitInsn(Opcodes.DUP); + code.visitLdcInsn("error marshalling arguments"); + code.visitVarInsn(Opcodes.ALOAD, var.deallocate("exception")); + code.visitMethodInsn + (Opcodes.INVOKESPECIAL, + Type.getInternalName(MarshalException.class), + "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, + new Type[] { Type.getType(String.class), + Type.getType(Exception.class) })); + code.visitInsn(Opcodes.ATHROW); + + code.visitLabel(endArgumentTryBlock); + code.visitTryCatchBlock + (beginArgumentTryBlock, iohandler, iohandler, + Type.getInternalName(IOException.class)); + + // this.ref.invoke(call) + code.visitVarInsn(Opcodes.ALOAD, var.get("this")); + code.visitFieldInsn + (Opcodes.GETFIELD, Type.getInternalName(RemoteObject.class), + "ref", Type.getDescriptor(RemoteRef.class)); + code.visitVarInsn(Opcodes.ALOAD, var.get("call")); + code.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(RemoteRef.class), + "invoke", + Type.getMethodDescriptor + (Type.VOID_TYPE, + new Type[] { Type.getType(RemoteCall.class) })); + + // handle return value + boolean needcastcheck = false; + + Label beginReturnTryCatch = new Label(); + code.visitLabel(beginReturnTryCatch); + + int returncode = returnOpcode(returntype); + + if (! returntype.equals(Void.TYPE)) + { + // call.getInputStream() + code.visitVarInsn(Opcodes.ALOAD, var.get("call")); + code.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(RemoteCall.class), + "getInputStream", + Type.getMethodDescriptor + (Type.getType(ObjectInput.class), new Type[] {})); + + Class readCls = + returntype.isPrimitive() ? returntype : Object.class; + code.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(ObjectInput.class), + readMethod(returntype), + Type.getMethodDescriptor + (Type.getType(readCls), new Type[] {})); + + boolean castresult = false; + + if (! returntype.isPrimitive()) + { + if (! returntype.equals(Object.class)) + castresult = true; + else + needcastcheck = true; + } + + if (castresult) + code.visitTypeInsn(Opcodes.CHECKCAST, typeArg(returntype)); + + // leave result on stack for return + } + + // this.ref.done(call) + code.visitVarInsn(Opcodes.ALOAD, var.get("this")); + code.visitFieldInsn + (Opcodes.GETFIELD, + Type.getInternalName(RemoteObject.class), + "ref", + Type.getDescriptor(RemoteRef.class)); + code.visitVarInsn(Opcodes.ALOAD, var.deallocate("call")); + code.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(RemoteRef.class), + "done", + Type.getMethodDescriptor + (Type.VOID_TYPE, + new Type[] { Type.getType(RemoteCall.class) })); + + // return; or return result; + code.visitInsn(returncode); + + // exception handler + Label handler = new Label(); + code.visitLabel(handler); + code.visitVarInsn(Opcodes.ASTORE, var.allocate("exception")); + + // throw new UnmarshalException(msg, e) + code.visitTypeInsn(Opcodes.NEW, typeArg(UnmarshalException.class)); + code.visitInsn(Opcodes.DUP); + code.visitLdcInsn("error unmarshalling return"); + code.visitVarInsn(Opcodes.ALOAD, var.deallocate("exception")); + code.visitMethodInsn + (Opcodes.INVOKESPECIAL, + Type.getInternalName(UnmarshalException.class), + "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, + new Type[] { Type.getType(String.class), + Type.getType(Exception.class) })); + code.visitInsn(Opcodes.ATHROW); + + Label endReturnTryCatch = new Label(); + + // catch IOException + code.visitTryCatchBlock + (beginReturnTryCatch, handler, handler, + Type.getInternalName(IOException.class)); + + if (needcastcheck) + { + // catch ClassNotFoundException + code.visitTryCatchBlock + (beginReturnTryCatch, handler, handler, + Type.getInternalName(ClassNotFoundException.class)); + } + } + + Label rethrowHandler = new Label(); + code.visitLabel(rethrowHandler); + // rethrow declared exceptions + code.visitInsn(Opcodes.ATHROW); + + boolean needgeneral = true; + for (int j = 0; j < except.length; j++) + { + if (except[j] == Exception.class) + needgeneral = false; + } + + for (int j = 0; j < except.length; j++) + { + code.visitTryCatchBlock + (methodTryBegin, rethrowHandler, rethrowHandler, + Type.getInternalName(except[j])); + } + + if (needgeneral) + { + // rethrow unchecked exceptions + code.visitTryCatchBlock + (methodTryBegin, rethrowHandler, rethrowHandler, + Type.getInternalName(RuntimeException.class)); + + Label generalHandler = new Label(); + code.visitLabel(generalHandler); + String msg = "undeclared checked exception"; + + // throw new java.rmi.UnexpectedException(msg, e) + code.visitVarInsn(Opcodes.ASTORE, var.allocate("exception")); + code.visitTypeInsn(Opcodes.NEW, typeArg(UnexpectedException.class)); + code.visitInsn(Opcodes.DUP); + code.visitLdcInsn(msg); + code.visitVarInsn(Opcodes.ALOAD, var.deallocate("exception")); + code.visitMethodInsn + (Opcodes.INVOKESPECIAL, + Type.getInternalName(UnexpectedException.class), + "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, + new Type [] { Type.getType(String.class), + Type.getType(Exception.class) })); + code.visitInsn(Opcodes.ATHROW); + + code.visitTryCatchBlock + (methodTryBegin, rethrowHandler, generalHandler, + Type.getInternalName(Exception.class)); + } + + code.visitMaxs(-1, -1); + } + + stub.visitEnd(); + byte[] classData = stub.toByteArray(); + if (!noWrite) + { + if (file.exists()) + file.delete(); + if (file.getParentFile() != null) + file.getParentFile().mkdirs(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(classData); + fos.flush(); + fos.close(); + } + } + + private void generateSkel() throws IOException + { + skelname = fullclassname + "_Skel"; + String skelclassname = classname + "_Skel"; + File file = new File(destination == null ? "" : destination + + File.separator + + skelname.replace('.', File.separatorChar) + + ".class"); + if (verbose) + System.out.println("[Generating class " + skelname + "]"); + + final ClassWriter skel = new ClassWriter(true); + classInternalName = skelname.replace('.', '/'); + skel.visit + (Opcodes.V1_1, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, + classInternalName, Type.getInternalName(Object.class), null, + new String[] { Type.getType(Skeleton.class).getInternalName() }); + + skel.visitField + (Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL, "interfaceHash", + Type.LONG_TYPE.getDescriptor(), null, + new Long(RMIHashes.getInterfaceHash(clazz))); + + skel.visitField + (Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL, "operations", + Type.getDescriptor(Operation[].class), null, null); + + MethodVisitor clinit = skel.visitMethod + (Opcodes.ACC_STATIC, "<clinit>", + Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}), null, null); + + fillOperationArray(clinit); + clinit.visitInsn(Opcodes.RETURN); + + clinit.visitMaxs(-1, -1); + + // no arg public constructor + MethodVisitor init = skel.visitMethod + (Opcodes.ACC_PUBLIC, "<init>", + Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}), null, null); + init.visitVarInsn(Opcodes.ALOAD, 0); + init.visitMethodInsn + (Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", + Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {})); + init.visitInsn(Opcodes.RETURN); + init.visitMaxs(-1, -1); + + /* + * public Operation[] getOperations() + * returns a clone of the operations array + */ + MethodVisitor getOp = skel.visitMethod + (Opcodes.ACC_PUBLIC, "getOperations", + Type.getMethodDescriptor + (Type.getType(Operation[].class), new Type[] {}), + null, null); + getOp.visitFieldInsn + (Opcodes.GETSTATIC, classInternalName, "operations", + Type.getDescriptor(Operation[].class)); + getOp.visitMethodInsn + (Opcodes.INVOKEVIRTUAL, Type.getInternalName(Object.class), + "clone", Type.getMethodDescriptor(Type.getType(Object.class), + new Type[] {})); + getOp.visitTypeInsn(Opcodes.CHECKCAST, typeArg(Operation[].class)); + getOp.visitInsn(Opcodes.ARETURN); + getOp.visitMaxs(-1, -1); + + // public void dispatch(Remote, RemoteCall, int opnum, long hash) + MethodVisitor dispatch = skel.visitMethod + (Opcodes.ACC_PUBLIC, + "dispatch", + Type.getMethodDescriptor + (Type.VOID_TYPE, + new Type[] { Type.getType(Remote.class), + Type.getType(RemoteCall.class), + Type.INT_TYPE, Type.LONG_TYPE }), null, + new String[] { Type.getInternalName(Exception.class) }); + + Variables var = new Variables(); + var.declare("this"); + var.declare("remoteobj"); + var.declare("remotecall"); + var.declare("opnum"); + var.declareWide("hash"); + + /* + * if opnum >= 0 + * XXX it is unclear why there is handling of negative opnums + */ + dispatch.visitVarInsn(Opcodes.ILOAD, var.get("opnum")); + Label nonNegativeOpnum = new Label(); + Label opnumSet = new Label(); + dispatch.visitJumpInsn(Opcodes.IFGE, nonNegativeOpnum); + + for (int i = 0; i < remotemethods.length; i++) + { + // assign opnum if hash matches supplied hash + dispatch.visitVarInsn(Opcodes.LLOAD, var.get("hash")); + dispatch.visitLdcInsn(new Long(remotemethods[i].hash)); + Label notIt = new Label(); + dispatch.visitInsn(Opcodes.LCMP); + dispatch.visitJumpInsn(Opcodes.IFNE, notIt); + + // opnum = <opnum> + dispatch.visitLdcInsn(new Integer(i)); + dispatch.visitVarInsn(Opcodes.ISTORE, var.get("opnum")); + dispatch.visitJumpInsn(Opcodes.GOTO, opnumSet); + dispatch.visitLabel(notIt); + } + + // throw new SkeletonMismatchException + Label mismatch = new Label(); + dispatch.visitJumpInsn(Opcodes.GOTO, mismatch); + + dispatch.visitLabel(nonNegativeOpnum); + + // if opnum is already set, check that the hash matches the interface + dispatch.visitVarInsn(Opcodes.LLOAD, var.get("hash")); + dispatch.visitFieldInsn + (Opcodes.GETSTATIC, classInternalName, + "interfaceHash", Type.LONG_TYPE.getDescriptor()); + dispatch.visitInsn(Opcodes.LCMP); + dispatch.visitJumpInsn(Opcodes.IFEQ, opnumSet); + + dispatch.visitLabel(mismatch); + dispatch.visitTypeInsn + (Opcodes.NEW, typeArg(SkeletonMismatchException.class)); + dispatch.visitInsn(Opcodes.DUP); + dispatch.visitLdcInsn("interface hash mismatch"); + dispatch.visitMethodInsn + (Opcodes.INVOKESPECIAL, + Type.getInternalName(SkeletonMismatchException.class), + "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, new Type[] { Type.getType(String.class) })); + dispatch.visitInsn(Opcodes.ATHROW); + + // opnum has been set + dispatch.visitLabel(opnumSet); + + dispatch.visitVarInsn(Opcodes.ALOAD, var.get("remoteobj")); + dispatch.visitTypeInsn(Opcodes.CHECKCAST, typeArg(clazz)); + dispatch.visitVarInsn(Opcodes.ASTORE, var.get("remoteobj")); + + Label deflt = new Label(); + Label[] methLabels = new Label[remotemethods.length]; + for (int i = 0; i < methLabels.length; i++) + methLabels[i] = new Label(); + + // switch on opnum + dispatch.visitVarInsn(Opcodes.ILOAD, var.get("opnum")); + dispatch.visitTableSwitchInsn + (0, remotemethods.length - 1, deflt, methLabels); + + // Method dispatch + for (int i = 0; i < remotemethods.length; i++) + { + dispatch.visitLabel(methLabels[i]); + Method m = remotemethods[i].meth; + generateMethodSkel(dispatch, m, var); + } + + dispatch.visitLabel(deflt); + dispatch.visitTypeInsn(Opcodes.NEW, typeArg(UnmarshalException.class)); + dispatch.visitInsn(Opcodes.DUP); + dispatch.visitLdcInsn("invalid method number"); + dispatch.visitMethodInsn + (Opcodes.INVOKESPECIAL, + Type.getInternalName(UnmarshalException.class), + "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, new Type[] { Type.getType(String.class) })); + dispatch.visitInsn(Opcodes.ATHROW); + + dispatch.visitMaxs(-1, -1); + + skel.visitEnd(); + byte[] classData = skel.toByteArray(); + if (!noWrite) + { + if (file.exists()) + file.delete(); + if (file.getParentFile() != null) + file.getParentFile().mkdirs(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(classData); + fos.flush(); + fos.close(); + } + } + + private void generateMethodSkel(MethodVisitor cv, Method m, Variables var) + { + Class[] sig = m.getParameterTypes(); + + Label readArgs = new Label(); + cv.visitLabel(readArgs); + + boolean needcastcheck = false; + + // ObjectInput in = call.getInputStream(); + cv.visitVarInsn(Opcodes.ALOAD, var.get("remotecall")); + cv.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(RemoteCall.class), "getInputStream", + Type.getMethodDescriptor + (Type.getType(ObjectInput.class), new Type[] {})); + cv.visitVarInsn(Opcodes.ASTORE, var.allocate("objectinput")); + + for (int i = 0; i < sig.length; i++) + { + // dup input stream + cv.visitVarInsn(Opcodes.ALOAD, var.get("objectinput")); + + Class readCls = sig[i].isPrimitive() ? sig[i] : Object.class; + + // in.readFoo() + cv.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(ObjectInput.class), + readMethod(sig[i]), + Type.getMethodDescriptor + (Type.getType(readCls), new Type [] {})); + + if (! sig[i].isPrimitive() && ! sig[i].equals(Object.class)) + { + needcastcheck = true; + cv.visitTypeInsn(Opcodes.CHECKCAST, typeArg(sig[i])); + } + + // store arg in variable + cv.visitVarInsn + (storeOpcode(sig[i]), var.allocate(param(m, i), size(sig[i]))); + } + + var.deallocate("objectinput"); + + Label doCall = new Label(); + Label closeInput = new Label(); + + cv.visitJumpInsn(Opcodes.JSR, closeInput); + cv.visitJumpInsn(Opcodes.GOTO, doCall); + + // throw new UnmarshalException + Label handler = new Label(); + cv.visitLabel(handler); + cv.visitVarInsn(Opcodes.ASTORE, var.allocate("exception")); + cv.visitTypeInsn(Opcodes.NEW, typeArg(UnmarshalException.class)); + cv.visitInsn(Opcodes.DUP); + cv.visitLdcInsn("error unmarshalling arguments"); + cv.visitVarInsn(Opcodes.ALOAD, var.deallocate("exception")); + cv.visitMethodInsn + (Opcodes.INVOKESPECIAL, + Type.getInternalName(UnmarshalException.class), + "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, new Type[] { Type.getType(String.class), + Type.getType(Exception.class) })); + cv.visitVarInsn(Opcodes.ASTORE, var.allocate("toThrow")); + cv.visitJumpInsn(Opcodes.JSR, closeInput); + cv.visitVarInsn(Opcodes.ALOAD, var.get("toThrow")); + cv.visitInsn(Opcodes.ATHROW); + + cv.visitTryCatchBlock + (readArgs, handler, handler, Type.getInternalName(IOException.class)); + if (needcastcheck) + { + cv.visitTryCatchBlock + (readArgs, handler, handler, + Type.getInternalName(ClassCastException.class)); + } + + // finally block + cv.visitLabel(closeInput); + cv.visitVarInsn(Opcodes.ASTORE, var.allocate("retAddress")); + cv.visitVarInsn(Opcodes.ALOAD, var.get("remotecall")); + cv.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(RemoteCall.class), + "releaseInputStream", + Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {})); + cv.visitVarInsn(Opcodes.RET, var.deallocate("retAddress")); + var.deallocate("toThrow"); + + // do the call using args stored as variables + cv.visitLabel(doCall); + cv.visitVarInsn(Opcodes.ALOAD, var.get("remoteobj")); + for (int i = 0; i < sig.length; i++) + cv.visitVarInsn(loadOpcode(sig[i]), var.deallocate(param(m, i))); + cv.visitMethodInsn + (Opcodes.INVOKEVIRTUAL, Type.getInternalName(clazz), m.getName(), + Type.getMethodDescriptor(m)); + + Class returntype = m.getReturnType(); + if (! returntype.equals(Void.TYPE)) + { + cv.visitVarInsn + (storeOpcode(returntype), var.allocate("result", size(returntype))); + } + + // write result to result stream + Label writeResult = new Label(); + cv.visitLabel(writeResult); + cv.visitVarInsn(Opcodes.ALOAD, var.get("remotecall")); + cv.visitInsn(Opcodes.ICONST_1); + cv.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(RemoteCall.class), + "getResultStream", + Type.getMethodDescriptor + (Type.getType(ObjectOutput.class), + new Type[] { Type.BOOLEAN_TYPE })); + + if (! returntype.equals(Void.TYPE)) + { + // out.writeFoo(result) + cv.visitVarInsn(loadOpcode(returntype), var.deallocate("result")); + Class writeCls = returntype.isPrimitive() ? returntype : Object.class; + cv.visitMethodInsn + (Opcodes.INVOKEINTERFACE, + Type.getInternalName(ObjectOutput.class), + writeMethod(returntype), + Type.getMethodDescriptor + (Type.VOID_TYPE, new Type[] { Type.getType(writeCls) })); + } + + cv.visitInsn(Opcodes.RETURN); + + // throw new MarshalException + Label marshalHandler = new Label(); + cv.visitLabel(marshalHandler); + cv.visitVarInsn(Opcodes.ASTORE, var.allocate("exception")); + cv.visitTypeInsn(Opcodes.NEW, typeArg(MarshalException.class)); + cv.visitInsn(Opcodes.DUP); + cv.visitLdcInsn("error marshalling return"); + cv.visitVarInsn(Opcodes.ALOAD, var.deallocate("exception")); + cv.visitMethodInsn + (Opcodes.INVOKESPECIAL, + Type.getInternalName(MarshalException.class), + "<init>", + Type.getMethodDescriptor + (Type.VOID_TYPE, new Type[] { Type.getType(String.class), + Type.getType(Exception.class) })); + cv.visitInsn(Opcodes.ATHROW); + cv.visitTryCatchBlock + (writeResult, marshalHandler, marshalHandler, + Type.getInternalName(IOException.class)); + } + + private static String typeArg(Class cls) + { + if (cls.isArray()) + return Type.getDescriptor(cls); + + return Type.getInternalName(cls); + } + + private static String readMethod(Class cls) + { + if (cls.equals(Void.TYPE)) + throw new IllegalArgumentException("can not read void"); + + String method; + if (cls.equals(Boolean.TYPE)) + method = "readBoolean"; + else if (cls.equals(Byte.TYPE)) + method = "readByte"; + else if (cls.equals(Character.TYPE)) + method = "readChar"; + else if (cls.equals(Short.TYPE)) + method = "readShort"; + else if (cls.equals(Integer.TYPE)) + method = "readInt"; + else if (cls.equals(Long.TYPE)) + method = "readLong"; + else if (cls.equals(Float.TYPE)) + method = "readFloat"; + else if (cls.equals(Double.TYPE)) + method = "readDouble"; + else + method = "readObject"; + + return method; + } + + private static String writeMethod(Class cls) + { + if (cls.equals(Void.TYPE)) + throw new IllegalArgumentException("can not read void"); + + String method; + if (cls.equals(Boolean.TYPE)) + method = "writeBoolean"; + else if (cls.equals(Byte.TYPE)) + method = "writeByte"; + else if (cls.equals(Character.TYPE)) + method = "writeChar"; + else if (cls.equals(Short.TYPE)) + method = "writeShort"; + else if (cls.equals(Integer.TYPE)) + method = "writeInt"; + else if (cls.equals(Long.TYPE)) + method = "writeLong"; + else if (cls.equals(Float.TYPE)) + method = "writeFloat"; + else if (cls.equals(Double.TYPE)) + method = "writeDouble"; + else + method = "writeObject"; + + return method; + } + + private static int returnOpcode(Class cls) + { + int returncode; + if (cls.equals(Boolean.TYPE)) + returncode = Opcodes.IRETURN; + else if (cls.equals(Byte.TYPE)) + returncode = Opcodes.IRETURN; + else if (cls.equals(Character.TYPE)) + returncode = Opcodes.IRETURN; + else if (cls.equals(Short.TYPE)) + returncode = Opcodes.IRETURN; + else if (cls.equals(Integer.TYPE)) + returncode = Opcodes.IRETURN; + else if (cls.equals(Long.TYPE)) + returncode = Opcodes.LRETURN; + else if (cls.equals(Float.TYPE)) + returncode = Opcodes.FRETURN; + else if (cls.equals(Double.TYPE)) + returncode = Opcodes.DRETURN; + else if (cls.equals(Void.TYPE)) + returncode = Opcodes.RETURN; + else + returncode = Opcodes.ARETURN; + + return returncode; + } + + private static int loadOpcode(Class cls) + { + if (cls.equals(Void.TYPE)) + throw new IllegalArgumentException("can not load void"); + + int loadcode; + if (cls.equals(Boolean.TYPE)) + loadcode = Opcodes.ILOAD; + else if (cls.equals(Byte.TYPE)) + loadcode = Opcodes.ILOAD; + else if (cls.equals(Character.TYPE)) + loadcode = Opcodes.ILOAD; + else if (cls.equals(Short.TYPE)) + loadcode = Opcodes.ILOAD; + else if (cls.equals(Integer.TYPE)) + loadcode = Opcodes.ILOAD; + else if (cls.equals(Long.TYPE)) + loadcode = Opcodes.LLOAD; + else if (cls.equals(Float.TYPE)) + loadcode = Opcodes.FLOAD; + else if (cls.equals(Double.TYPE)) + loadcode = Opcodes.DLOAD; + else + loadcode = Opcodes.ALOAD; + + return loadcode; + } + + private static int storeOpcode(Class cls) + { + if (cls.equals(Void.TYPE)) + throw new IllegalArgumentException("can not load void"); + + int storecode; + if (cls.equals(Boolean.TYPE)) + storecode = Opcodes.ISTORE; + else if (cls.equals(Byte.TYPE)) + storecode = Opcodes.ISTORE; + else if (cls.equals(Character.TYPE)) + storecode = Opcodes.ISTORE; + else if (cls.equals(Short.TYPE)) + storecode = Opcodes.ISTORE; + else if (cls.equals(Integer.TYPE)) + storecode = Opcodes.ISTORE; + else if (cls.equals(Long.TYPE)) + storecode = Opcodes.LSTORE; + else if (cls.equals(Float.TYPE)) + storecode = Opcodes.FSTORE; + else if (cls.equals(Double.TYPE)) + storecode = Opcodes.DSTORE; + else + storecode = Opcodes.ASTORE; + + return storecode; + } + + private static String unboxMethod(Class primitive) + { + if (! primitive.isPrimitive()) + throw new IllegalArgumentException("can not unbox nonprimitive"); + + String method; + if (primitive.equals(Boolean.TYPE)) + method = "booleanValue"; + else if (primitive.equals(Byte.TYPE)) + method = "byteValue"; + else if (primitive.equals(Character.TYPE)) + method = "charValue"; + else if (primitive.equals(Short.TYPE)) + method = "shortValue"; + else if (primitive.equals(Integer.TYPE)) + method = "intValue"; + else if (primitive.equals(Long.TYPE)) + method = "longValue"; + else if (primitive.equals(Float.TYPE)) + method = "floatValue"; + else if (primitive.equals(Double.TYPE)) + method = "doubleValue"; + else + throw new IllegalStateException("unknown primitive class " + primitive); + + return method; + } + + public static Class box(Class cls) + { + if (! cls.isPrimitive()) + throw new IllegalArgumentException("can only box primitive"); + + Class box; + if (cls.equals(Boolean.TYPE)) + box = Boolean.class; + else if (cls.equals(Byte.TYPE)) + box = Byte.class; + else if (cls.equals(Character.TYPE)) + box = Character.class; + else if (cls.equals(Short.TYPE)) + box = Short.class; + else if (cls.equals(Integer.TYPE)) + box = Integer.class; + else if (cls.equals(Long.TYPE)) + box = Long.class; + else if (cls.equals(Float.TYPE)) + box = Float.class; + else if (cls.equals(Double.TYPE)) + box = Double.class; + else + throw new IllegalStateException("unknown primitive type " + cls); + + return box; + } + + private static int size(Class cls) { + if (cls.equals(Long.TYPE) || cls.equals(Double.TYPE)) + return 2; + else + return 1; + } + + /** + * Sort exceptions so the most general go last. + */ + private Class[] sortExceptions(Class[] except) + { + for (int i = 0; i < except.length; i++) + { + for (int j = i + 1; j < except.length; j++) + { + if (except[i].isAssignableFrom(except[j])) + { + Class tmp = except[i]; + except[i] = except[j]; + except[j] = tmp; + } + } + } + return (except); + } + + public void setup(boolean keep, boolean need11Stubs, boolean need12Stubs, + boolean iiop, boolean poa, boolean debug, boolean warnings, + boolean noWrite, boolean verbose, boolean force, String classpath, + String bootclasspath, String extdirs, String outputDirectory) + { + this.keep = keep; + this.need11Stubs = need11Stubs; + this.need12Stubs = need12Stubs; + this.verbose = verbose; + this.noWrite = noWrite; + + // Set up classpath. + this.classpath = classpath; + StringTokenizer st = + new StringTokenizer(classpath, File.pathSeparator); + URL[] u = new URL[st... [truncated message content] |
From: <ls...@us...> - 2007-01-07 12:59:53
|
Revision: 3026 http://jnode.svn.sourceforge.net/jnode/?rev=3026&view=rev Author: lsantha Date: 2007-01-07 04:59:51 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/tools/gnu/classpath/tools/rmid/ActivationSystemImpl.java trunk/core/src/classpath/vm/java/lang/Class.java trunk/core/src/classpath/vm/java/lang/Thread.java trunk/core/src/classpath/vm/java/lang/VMSystem.java trunk/core/src/classpath/vm/java/lang/reflect/Method.java Added Paths: ----------- trunk/core/src/classpath/vm/java/lang/VMProcess.java Modified: trunk/core/src/classpath/tools/gnu/classpath/tools/rmid/ActivationSystemImpl.java =================================================================== --- trunk/core/src/classpath/tools/gnu/classpath/tools/rmid/ActivationSystemImpl.java 2007-01-07 12:57:57 UTC (rev 3025) +++ trunk/core/src/classpath/tools/gnu/classpath/tools/rmid/ActivationSystemImpl.java 2007-01-07 12:59:51 UTC (rev 3026) @@ -238,6 +238,6 @@ ClassNotFoundException { // Write no fields. - }; + } } Modified: trunk/core/src/classpath/vm/java/lang/Class.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/Class.java 2007-01-07 12:57:57 UTC (rev 3025) +++ trunk/core/src/classpath/vm/java/lang/Class.java 2007-01-07 12:59:51 UTC (rev 3026) @@ -1,24 +1,41 @@ -/* - * $Id$ - * - * JNode.org - * Copyright (C) 2003-2006 JNode.org - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; If not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ +/* Class.java -- Representation of a Java class. + Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + package java.lang; import gnu.java.lang.VMClassHelper; @@ -56,10 +73,34 @@ import org.jnode.vm.classmgr.VmType; /** - * Class. If you change any fields in this class, also change - * <code>emitClass</code> in <code>org.jnode.build.ObjectEmitter</code>. + * A Class represents a Java type. There will never be multiple Class + * objects with identical names and ClassLoaders. Primitive types, array + * types, and void also have a Class object. * - * @author epr + * <p>Arrays with identical type and number of dimensions share the same class. + * The array class ClassLoader is the same as the ClassLoader of the element + * type of the array (which can be null to indicate the bootstrap classloader). + * The name of an array class is <code>[<signature format>;</code>. + * <p> For example, + * String[]'s class is <code>[Ljava.lang.String;</code>. boolean, byte, + * short, char, int, long, float and double have the "type name" of + * Z,B,S,C,I,J,F,D for the purposes of array classes. If it's a + * multidimensioned array, the same principle applies: + * <code>int[][][]</code> == <code>[[[I</code>. + * + * <p>There is no public constructor - Class objects are obtained only through + * the virtual machine, as defined in ClassLoaders. + * + * @serialData Class objects serialize specially: + * <code>TC_CLASS ClassDescriptor</code>. For more serialization information, + * see {@link ObjectStreamClass}. + * + * @author John Keiser + * @author Eric Blake (eb...@em...) + * @author Tom Tromey (tr...@re...) + * @author Andrew John Hughes (gnu...@me...) + * @since 1.0 + * @see ClassLoader */ public final class Class<T> implements AnnotatedElement, Serializable, Type, GenericDeclaration { @@ -369,7 +410,7 @@ * @throws InstantiationException * @throws IllegalAccessException */ - public final Object newInstance() throws InstantiationException, + public final T newInstance() throws InstantiationException, IllegalAccessException { if (defaultConstructor == null) { defaultConstructor = getLinkedVmClass().getDeclaredMethod("<init>", @@ -379,7 +420,7 @@ throw new InstantiationException("No default constructor"); } try { - return VmReflection.newInstance(defaultConstructor); + return (T)VmReflection.newInstance(defaultConstructor); } catch (InvocationTargetException ex) { final InstantiationException ie = new InstantiationException(); ie.initCause(ex); Modified: trunk/core/src/classpath/vm/java/lang/Thread.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/Thread.java 2007-01-07 12:57:57 UTC (rev 3025) +++ trunk/core/src/classpath/vm/java/lang/Thread.java 2007-01-07 12:59:51 UTC (rev 3026) @@ -1,21 +1,18 @@ -/* - * $Id$ +/* Thread -- an independent thread of executable code + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 * - * JNode.org - * Copyright (C) 2003-2006 JNode.org - * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * - * This library is distributed in the hope that it will be useful, but + * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with this library; If not, write to the Free Software Foundation, Inc., + * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -712,7 +709,37 @@ } return locals; } + /** + * <p> + * Represents the current state of a thread, according to the VM rather + * than the operating system. It can be one of the following: + * </p> + * <ul> + * <li>NEW -- The thread has just been created but is not yet running.</li> + * <li>RUNNABLE -- The thread is currently running or can be scheduled + * to run.</li> + * <li>BLOCKED -- The thread is blocked waiting on an I/O operation + * or to obtain a lock.</li> + * <li>WAITING -- The thread is waiting indefinitely for another thread + * to do something.</li> + * <li>TIMED_WAITING -- The thread is waiting for a specific amount of time + * for another thread to do something.</li> + * <li>TERMINATED -- The thread has exited.</li> + * </ul> + * + * @since 1.5 + */ + public enum State + { + BLOCKED, NEW, RUNNABLE, TERMINATED, TIMED_WAITING, WAITING; + /** + * For compatability with Sun's JDK + */ + private static final long serialVersionUID = 605505746047245783L; + } + + /** * Returns the current state of the thread. This * is designed for monitoring thread behaviour, rather @@ -720,9 +747,9 @@ * * @return the current thread state. */ - public String getState() + public State getState() { //todo implement - return "UNKNOWN"; + throw new UnsupportedClassVersionError(); } } Added: trunk/core/src/classpath/vm/java/lang/VMProcess.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/VMProcess.java (rev 0) +++ trunk/core/src/classpath/vm/java/lang/VMProcess.java 2007-01-07 12:59:51 UTC (rev 3026) @@ -0,0 +1,410 @@ +/* java.lang.VMProcess -- VM implementation of java.lang.Process + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * Represents one external process. Each instance of this class is in + * one of three states: INITIAL, RUNNING, or TERMINATED. The instance + * is {@link Object#notifyAll notifyAll()}'d each time the state changes. + * The state of all instances is managed by a single dedicated thread + * which does the actual fork()/exec() and wait() system calls. User + * threads {@link Object#wait()} on the instance when creating the + * process or waiting for it to terminate. + * + * <p> + * See + * <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11801">GCC bug + * #11801</a> for the motivation behind the design of this class. + * + * @author Archie Cobbs + * @see Process + * @see Runtime#exec(String) + */ +final class VMProcess extends Process +{ + + // Possible states for a VMProcess + private static final int INITIAL = 0; + private static final int RUNNING = 1; + private static final int TERMINATED = 2; + + // Dedicated thread that does all the fork()'ing and wait()'ing. + static Thread processThread; + + // New processes waiting to be spawned by processThread. + static final LinkedList workList = new LinkedList(); + + // Return values set by nativeReap() when a child is reaped. + // These are only accessed by processThread so no locking required. + static long reapedPid; + static int reapedExitValue; + + // Information about this process + int state; // current state of process + final String[] cmd; // copied from Runtime.exec() + final String[] env; // copied from Runtime.exec() + final File dir; // copied from Runtime.exec() + Throwable exception; // if process failed to start + long pid; // process id + OutputStream stdin; // process input stream + InputStream stdout; // process output stream + InputStream stderr; // process error stream + int exitValue; // process exit value + boolean redirect; // redirect stderr -> stdout + + // + // Dedicated thread that does all the fork()'ing and wait()'ing + // for external processes. This is needed because some systems like + // Linux use a process-per-thread model, which means the same thread + // that did the fork()/exec() must also do the wait(). + // + private static class ProcessThread extends Thread + { + + // Max time (in ms) we'll delay before trying to reap another child. + private static final int MAX_REAP_DELAY = 1000; + + // Processes created but not yet terminated; maps Long(pid) -> VMProcess + // Only used in run() and spawn() method from this Thread, so no locking. + private final HashMap activeMap = new HashMap(); + + // We have an explicit constructor, because the default + // constructor will be private, which means the compiler will have + // to generate a second package-private constructor, which is + // bogus. + ProcessThread () + { + } + + public void run() + { + final LinkedList workList = VMProcess.workList; + while (true) + { + + // Get the next process to spawn (if any) and spawn it. Spawn + // at most one at a time before checking for reapable children. + VMProcess process = null; + synchronized (workList) + { + if (!workList.isEmpty()) + process = (VMProcess)workList.removeFirst(); + } + + if (process != null) + spawn(process); + + + // Check for termination of active child processes + while (!activeMap.isEmpty() && VMProcess.nativeReap()) + { + long pid = VMProcess.reapedPid; + int exitValue = VMProcess.reapedExitValue; + process = (VMProcess)activeMap.remove(new Long(pid)); + if (process != null) + { + synchronized (process) + { + process.exitValue = exitValue; + process.state = TERMINATED; + process.notify(); + } + } + else + System.err.println("VMProcess WARNING reaped unknown process: " + + pid); + } + + + // If there are more new processes to create, go do that now. + // If there is nothing left to do, exit this thread. Otherwise, + // sleep a little while, and then check again for reapable children. + // We will get woken up immediately if there are new processes to + // spawn, but not if there are new children to reap. So we only + // sleep a short time, in effect polling while processes are active. + synchronized (workList) + { + if (!workList.isEmpty()) + continue; + if (activeMap.isEmpty()) + { + processThread = null; + break; + } + + try + { + workList.wait(MAX_REAP_DELAY); + } + catch (InterruptedException e) + { + /* ignore */ + } + } + } + } + + // Spawn a process + private void spawn(VMProcess process) + { + + // Spawn the process and put it in our active map indexed by pid. + // If the spawn operation fails, store the exception with the process. + // In either case, wake up thread that created the process. + synchronized (process) + { + try + { + process.nativeSpawn(process.cmd, process.env, process.dir, + process.redirect); + process.state = RUNNING; + activeMap.put(new Long(process.pid), process); + } + catch (ThreadDeath death) + { + throw death; + } + catch (Throwable t) + { + process.state = TERMINATED; + process.exception = t; + } + process.notify(); + } + } + } + + // Constructor + private VMProcess(String[] cmd, String[] env, File dir, boolean redirect) + throws IOException + { + + // Initialize this process + this.state = INITIAL; + this.cmd = cmd; + this.env = env; + this.dir = dir; + this.redirect = redirect; + + // Add process to the new process work list and wakeup processThread + synchronized (workList) + { + workList.add(this); + if (processThread == null) + { + processThread = new ProcessThread(); + processThread.setDaemon(true); + processThread.start(); + } + else + { + workList.notify(); + } + } + + // Wait for processThread to spawn this process and update its state + synchronized (this) + { + while (state == INITIAL) + { + try + { + wait(); + } + catch (InterruptedException e) + { + /* ignore */ + } + } + } + + // If spawning failed, rethrow the exception in this thread + if (exception != null) + { + exception.fillInStackTrace(); + if (exception instanceof IOException) + throw (IOException)exception; + + if (exception instanceof Error) + throw (Error)exception; + + if (exception instanceof RuntimeException) + throw (RuntimeException)exception; + + throw new RuntimeException(exception); + } + } + + // Invoked by native code (from nativeSpawn()) to record process info. + private void setProcessInfo(OutputStream stdin, + InputStream stdout, InputStream stderr, long pid) + { + this.stdin = stdin; + this.stdout = stdout; + if (stderr == null) + this.stderr = new InputStream() + { + public int read() throws IOException + { + return -1; + } + }; + else + this.stderr = stderr; + this.pid = pid; + } + + /** + * Entry point from Runtime.exec(). + */ + static Process exec(String[] cmd, String[] env, File dir) throws IOException + { + return new VMProcess(cmd, env, dir, false); + } + + static Process exec(List cmd, Map env, + File dir, boolean redirect) throws IOException + { + String[] acmd = (String[]) cmd.toArray(new String[cmd.size()]); + String[] aenv = new String[env.size()]; + + int i = 0; + Iterator iter = env.entrySet().iterator(); + while (iter.hasNext()) + { + Map.Entry entry = (Map.Entry) iter.next(); + aenv[i++] = entry.getKey() + "=" + entry.getValue(); + } + + return new VMProcess(acmd, aenv, dir, redirect); + } + + public OutputStream getOutputStream() + { + return stdin; + } + + public InputStream getInputStream() + { + return stdout; + } + + public InputStream getErrorStream() + { + return stderr; + } + + public synchronized int waitFor() throws InterruptedException + { + while (state != TERMINATED) + wait(); + return exitValue; + } + + public synchronized int exitValue() + { + if (state != TERMINATED) + throw new IllegalThreadStateException(); + return exitValue; + } + + public synchronized void destroy() + { + if (state == TERMINATED) + return; + + nativeKill(pid); + + while (state != TERMINATED) + { + try + { + wait(); + } + catch (InterruptedException e) + { + /* ignore */ + } + } + } + + /** + * Does the fork()/exec() thing to create the O/S process. + * Must invoke setProcessInfo() before returning successfully. + * This method is only invoked by processThread. + * + * @throws IOException if the O/S process could not be created. + */ + void nativeSpawn(String[] cmd, String[] env, File dir, + boolean redirect) throws IOException{ + //TODO implement it + throw new UnsupportedOperationException(); + }; + + /** + * Test for a reapable child process, and reap if so. Does not block. + * If a child was reaped, this method must set reapedPid and + * reapedExitValue appropriately before returning. + * This method is only invoked by processThread. + * + * @return true if a child was reaped, otherwise false + */ + // This is not private as it is called from an inner class. + static boolean nativeReap(){ + //TODO implement it + throw new UnsupportedOperationException(); + } + + /** + * Kill a process. This sends it a fatal signal but does not reap it. + */ + private static void nativeKill(long pid){ + //TODO implement it + throw new UnsupportedOperationException(); + } +} Modified: trunk/core/src/classpath/vm/java/lang/VMSystem.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/VMSystem.java 2007-01-07 12:57:57 UTC (rev 3025) +++ trunk/core/src/classpath/vm/java/lang/VMSystem.java 2007-01-07 12:59:51 UTC (rev 3026) @@ -1,29 +1,46 @@ -/* - * $Id$ - * - * JNode.org - * Copyright (C) 2003-2006 JNode.org - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; If not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ +/* VMSystem.java -- helper for java.lang.system + Copyright (C) 1998, 2002, 2004 Free Software Foundation +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + package java.lang; import java.io.InputStream; import java.io.PrintStream; import java.nio.ByteOrder; +import java.util.List; import org.jnode.util.EmptyInputStream; import org.jnode.util.SystemInputStream; @@ -152,14 +169,53 @@ return VmSystem.currentTimeMillis(); } - /** + /** + * <p> + * Returns the current value of a nanosecond-precise system timer. + * The value of the timer is an offset relative to some arbitrary fixed + * time, which may be in the future (making the value negative). This + * method is useful for timing events where nanosecond precision is + * required. This is achieved by calling this method before and after the + * event, and taking the difference betweent the two times: + * </p> + * <p> + * <code>long startTime = System.nanoTime();</code><br /> + * <code>... <emph>event code</emph> ...</code><br /> + * <code>long endTime = System.nanoTime();</code><br /> + * <code>long duration = endTime - startTime;</code><br /> + * </p> + * <p> + * Note that the value is only nanosecond-precise, and not accurate; there + * is no guarantee that the difference between two values is really a + * nanosecond. Also, the value is prone to overflow if the offset + * exceeds 2^63. + * </p> + * + * @return the time of a system timer in nanoseconds. + * @since 1.5 + */ + public static long nanoTime(){ + //TODO implement it + throw new UnsupportedOperationException(); + }; + + /** + * Returns a list of 'name=value' pairs representing the current environment + * variables. + * + * @return a list of 'name=value' pairs. + */ + static List environ(){ + //TODO implement it + throw new UnsupportedOperationException(); + } + /** * Helper method which creates the standard input stream. VM implementors * may choose to construct these streams differently. This method can also * return null if the stream is created somewhere else in the VM startup * sequence. */ - - static InputStream makeStandardInputStream() { + static InputStream makeStandardInputStream() { return SystemInputStream.getInstance(); // JNode specific } @@ -169,7 +225,6 @@ * return null if the stream is created somewhere else in the VM startup * sequence. */ - static PrintStream makeStandardOutputStream() { return VmSystem.getSystemOut(); } Modified: trunk/core/src/classpath/vm/java/lang/reflect/Method.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/reflect/Method.java 2007-01-07 12:57:57 UTC (rev 3025) +++ trunk/core/src/classpath/vm/java/lang/reflect/Method.java 2007-01-07 12:59:51 UTC (rev 3026) @@ -323,7 +323,7 @@ * @throws ExceptionInInitializerError if accessing a static method triggered * class initialization, which then failed */ - public Object invoke(Object o, Object[] args) + public Object invoke(Object o, Object... args) throws IllegalAccessException, InvocationTargetException { return VmReflection.invoke(vmMethod, o, args); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-07 12:57:58
|
Revision: 3025 http://jnode.svn.sourceforge.net/jnode/?rev=3025&view=rev Author: lsantha Date: 2007-01-07 04:57:57 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/javax/javax/crypto/CipherOutputStream.java trunk/core/src/classpath/javax/javax/crypto/Mac.java trunk/core/src/classpath/javax/javax/crypto/MacSpi.java trunk/core/src/classpath/javax/javax/net/ssl/HandshakeCompletedEvent.java trunk/core/src/classpath/javax/javax/net/ssl/HttpsURLConnection.java trunk/core/src/classpath/javax/javax/net/ssl/SSLContext.java trunk/core/src/classpath/javax/javax/net/ssl/SSLContextSpi.java trunk/core/src/classpath/javax/javax/net/ssl/SSLServerSocketFactory.java trunk/core/src/classpath/javax/javax/net/ssl/SSLSession.java trunk/core/src/classpath/javax/javax/net/ssl/SSLSocketFactory.java Added Paths: ----------- trunk/core/src/classpath/javax/javax/management/MBeanServerPermission.java trunk/core/src/classpath/javax/javax/net/ssl/CertPathTrustManagerParameters.java trunk/core/src/classpath/javax/javax/net/ssl/KeyStoreBuilderParameters.java trunk/core/src/classpath/javax/javax/net/ssl/SSLEngine.java trunk/core/src/classpath/javax/javax/net/ssl/SSLEngineResult.java trunk/core/src/classpath/javax/javax/net/ssl/X509ExtendedKeyManager.java trunk/core/src/classpath/javax/javax/swing/text/html/CSSParser.java Modified: trunk/core/src/classpath/javax/javax/crypto/CipherOutputStream.java =================================================================== --- trunk/core/src/classpath/javax/javax/crypto/CipherOutputStream.java 2007-01-07 12:55:51 UTC (rev 3024) +++ trunk/core/src/classpath/javax/javax/crypto/CipherOutputStream.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -50,33 +50,12 @@ */ public class CipherOutputStream extends FilterOutputStream { - - // Fields. - // ------------------------------------------------------------------------ - /** The underlying cipher. */ private Cipher cipher; - private byte[][] inBuffer; - - private int inLength; - - private byte[] outBuffer; - - private static final int FIRST_TIME = 0; - private static final int SECOND_TIME = 1; - private static final int SEASONED = 2; - private int state; - - /** True if the cipher is a stream cipher (blockSize == 1) */ - private boolean isStream; - - // Constructors. - // ------------------------------------------------------------------------ - /** - * Create a new cipher output stream. The cipher argument must have - * already been initialized. + * Create a new cipher output stream. The cipher argument must have already + * been initialized. * * @param out The sink for transformed data. * @param cipher The cipher to transform data with. @@ -84,20 +63,7 @@ public CipherOutputStream(OutputStream out, Cipher cipher) { super(out); - if (cipher != null) - { - this.cipher = cipher; - if (!(isStream = cipher.getBlockSize() == 1)) - { - inBuffer = new byte[2][]; - inBuffer[0] = new byte[cipher.getBlockSize()]; - inBuffer[1] = new byte[cipher.getBlockSize()]; - inLength = 0; - state = FIRST_TIME; - } - } - else - this.cipher = new NullCipher(); + this.cipher = (cipher != null) ? cipher : new NullCipher(); } /** @@ -110,52 +76,36 @@ super(out); } - // Instance methods. - // ------------------------------------------------------------------------ - /** * Close this output stream, and the sink output stream. + * <p> + * This method will first invoke the {@link Cipher#doFinal()} method of the + * underlying {@link Cipher}, and writes the output of that method to the + * sink output stream. * - * <p>This method will first invoke the {@link Cipher#doFinal()} - * method of the underlying {@link Cipher}, and writes the output of - * that method to the sink output stream. - * - * @throws java.io.IOException If an I/O error occurs, or if an error - * is caused by finalizing the transformation. + * @throws IOException If an I/O error occurs, or if an error is caused by + * finalizing the transformation. */ public void close() throws IOException { try { - int len; - if (state != FIRST_TIME) - { - len = cipher.update(inBuffer[0], 0, inBuffer[0].length, outBuffer); - out.write(outBuffer, 0, len); - } - len = cipher.doFinal(inBuffer[0], 0, inLength, outBuffer); - out.write(outBuffer, 0, len); + out.write(cipher.doFinal()); + out.flush(); + out.close(); } - catch (javax.crypto.IllegalBlockSizeException ibse) + catch (Exception cause) { - throw new IOException(ibse.toString()); + IOException ioex = new IOException(String.valueOf(cause)); + ioex.initCause(cause); + throw ioex; } - catch (javax.crypto.BadPaddingException bpe) - { - throw new IOException(bpe.toString()); - } - catch (ShortBufferException sbe) - { - throw new IOException(sbe.toString()); - } - out.flush(); - out.close(); } /** * Flush any pending output. * - * @throws java.io.IOException If an I/O error occurs. + * @throws IOException If an I/O error occurs. */ public void flush() throws IOException { @@ -166,38 +116,20 @@ * Write a single byte to the output stream. * * @param b The next byte. - * @throws java.io.IOException If an I/O error occurs, or if the - * underlying cipher is not in the correct state to transform - * data. + * @throws IOException If an I/O error occurs, or if the underlying cipher is + * not in the correct state to transform data. */ public void write(int b) throws IOException { - if (isStream) - { - byte[] buf = new byte[] { (byte) b }; - try - { - cipher.update(buf, 0, 1, buf, 0); - } - catch (ShortBufferException sbe) - { - throw new IOException(sbe.toString()); - } - out.write(buf); - return; - } - inBuffer[1][inLength++] = (byte) b; - if (inLength == inBuffer[1].length) - process(); + write(new byte[] { (byte) b }, 0, 1); } /** * Write a byte array to the output stream. * * @param buf The next bytes. - * @throws java.io.IOException If an I/O error occurs, or if the - * underlying cipher is not in the correct state to transform - * data. + * @throws IOException If an I/O error occurs, or if the underlying cipher is + * not in the correct state to transform data. */ public void write(byte[] buf) throws IOException { @@ -210,59 +142,11 @@ * @param buf The next bytes. * @param off The offset in the byte array to start. * @param len The number of bytes to write. - * @throws java.io.IOException If an I/O error occurs, or if the - * underlying cipher is not in the correct state to transform - * data. + * @throws IOException If an I/O error occurs, or if the underlying cipher is + * not in the correct state to transform data. */ public void write(byte[] buf, int off, int len) throws IOException { - if (isStream) - { out.write(cipher.update(buf, off, len)); - return; - } - int count = 0; - while (count < len) - { - int l = Math.min(inBuffer[1].length - inLength, len - count); - System.arraycopy(buf, off+count, inBuffer[1], inLength, l); - count += l; - inLength += l; - if (inLength == inBuffer[1].length) - process(); - } } - - // Own method. - // ------------------------------------------------------------------------- - - private void process() throws IOException - { - if (state == SECOND_TIME) - { - state = SEASONED; - } - else - { - byte[] temp = inBuffer[0]; - inBuffer[0] = inBuffer[1]; - inBuffer[1] = temp; - } - if (state == FIRST_TIME) - { - inLength = 0; - state = SECOND_TIME; - return; - } - try - { - cipher.update(inBuffer[0], 0, inBuffer[0].length, outBuffer); - } - catch (ShortBufferException sbe) - { - throw new IOException(sbe.toString()); - } - out.write(outBuffer); - inLength = 0; - } } Modified: trunk/core/src/classpath/javax/javax/crypto/Mac.java =================================================================== --- trunk/core/src/classpath/javax/javax/crypto/Mac.java 2007-01-07 12:55:51 UTC (rev 3024) +++ trunk/core/src/classpath/javax/javax/crypto/Mac.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -41,6 +41,7 @@ import gnu.java.security.Engine; import java.lang.reflect.InvocationTargetException; +import java.nio.ByteBuffer; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; @@ -406,6 +407,18 @@ } /** + * Update this MAC with the remaining bytes in the given buffer + * @param buffer The input buffer. + * @since 1.5 + */ + public final void update (final ByteBuffer buffer) + { + if (virgin) + throw new IllegalStateException ("not initialized"); + macSpi.engineUpdate(buffer); + } + + /** * Clone this instance, if the underlying implementation supports it. * * @return A clone of this instance. Modified: trunk/core/src/classpath/javax/javax/crypto/MacSpi.java =================================================================== --- trunk/core/src/classpath/javax/javax/crypto/MacSpi.java 2007-01-07 12:55:51 UTC (rev 3024) +++ trunk/core/src/classpath/javax/javax/crypto/MacSpi.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -38,6 +38,7 @@ package javax.crypto; +import java.nio.ByteBuffer; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; @@ -142,4 +143,21 @@ * @param length The number of bytes to update. */ protected abstract void engineUpdate(byte[] input, int offset, int length); + + /** + * Update this MAC with the remaining bytes of a buffer. + * + * @param buffer The input buffer. + * @since 1.5 + */ + protected void engineUpdate (final ByteBuffer buffer) + { + byte[] buf = new byte[1024]; + while (buffer.hasRemaining ()) + { + int n = Math.min (buffer.remaining (), buf.length); + buffer.get (buf, 0, n); + engineUpdate (buf, 0, n); + } + } } Added: trunk/core/src/classpath/javax/javax/management/MBeanServerPermission.java =================================================================== --- trunk/core/src/classpath/javax/javax/management/MBeanServerPermission.java (rev 0) +++ trunk/core/src/classpath/javax/javax/management/MBeanServerPermission.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -0,0 +1,470 @@ +/* MBeanServerPermission.java -- Permissions controlling server creation. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.management; + +import java.security.BasicPermission; +import java.security.Permission; +import java.security.PermissionCollection; + +import java.util.Enumeration; +import java.util.NoSuchElementException; + +/** + * <p> + * Represents the permissions required to perform + * operations provided by the {@link MBeanServerFactory}. + * As with all {@link java.security.Permission} objects, an + * instance of this class either represents a permission + * already held or one that is required to access a + * particular service. In the case of {@link MBeanServerPermission}s, + * implication checks are made using an instance of this class + * when a user requests an operation from the factory, and a + * {@link SecurityManager} is in place. + * </p> + * <p> + * The permission is defined by its name, which may be + * either a <code>'*'</code> (to allow all) or one or + * more of the following, separated by a <code>','</code>: + * </p> + * <ul> + * <li><code>createMBeanServer</code> -- allows a registered + * instance of a server to be obtained from the factory.</li> + * <li><code>findMBeanServer</code> -- allows all or one + * particular server instance to be retrieved from the factory.</li> + * <li><code>newMBeanServer</code> -- allows an unregistered + * instance of a server to be obtained from the factory.</li> + * <li><code>releaseMBeanServer</code> -- allows a reference to + * a server instance to be removed from the factory.</li> + * </ul> + * <p> + * The names may be surrounded by arbitrary amounts of whitespace. + * <code>createMBeanServer</code> implies <code>newMBeanServer</code>. + * </p> + * + * @author Andrew John Hughes (gnu...@me...) + * @since 1.5 + */ +public class MBeanServerPermission + extends BasicPermission +{ + + /** + * Compatible with JDK 1.5 + */ + private static final long serialVersionUID = -5661980843569388590L; + + /** + * <p> + * Constructs a new {@link MBeanServerPermission} with + * the given name. The name must not be <code>null</code> + * and must be equal to either <code>"*"</code> or a + * comma-separated list of valid permissions. The four + * valid constraints are: + * </p> + * <ol> + * <li><code>createMBeanServer</code></li> + * <li><code>findMBeanServer</code></li> + * <li><code>newMBeanServer</code></li> + * <li><code>releaseMBeanServer</code></li> + * </ol> + * <p> + * Calling this constructor is equivalent to calling + * <code>MBeanPermission(name, null)</code>. + * </p> + * + * @param name the name of this permission. + * @throws NullPointerException if <code>name</code> + * is <code>null</code>. + * @throws IllegalArgumentException if <code>name</code> + * is not either equal to + * <code>"*"</code> or forms + * a comma-separated list of + * valid constraints. + * @see #MBeanServerPermission(String,String) + */ + public MBeanServerPermission(String name) + { + this(name, null); + } + + /** + * <p> + * Constructs a new {@link MBeanServerPermission} with + * the given name and actions. The actions are unused, + * and must be either <code>null</code> or the empty + * string. The name must not be <code>null</code> + * and must be equal to either <code>"*"</code> or a + * comma-separated list of valid permissions. The four + * valid constraints are: + * </p> + * <ol> + * <li><code>createMBeanServer</code></li> + * <li><code>findMBeanServer</code></li> + * <li><code>newMBeanServer</code></li> + * <li><code>releaseMBeanServer</code></li> + * </ol> + * <p> + * Calling this constructor is equivalent to calling + * <code>MBeanPermission(name, null)</code>. + * </p> + * + * @param name the name of this permission. + * @throws NullPointerException if <code>name</code> + * is <code>null</code>. + * @throws IllegalArgumentException if <code>name</code> + * is not either equal to + * <code>"*"</code> or forms + * a comma-separated list of + * valid constraints, or if + * <code>actions</code> is not + * <code>null</code> or the + * empty string. + * @see #MBeanServerPermission(String,String) + */ + public MBeanServerPermission(String name, String actions) + { + super(checkName(name), actions); + if (actions != null && actions.length() > 0) + throw new IllegalArgumentException("The supplied action list " + + "was not equal to null or the " + + "empty string."); + } + + /** + * Returns true if the given object is also an {@link MBeanServerPermission} + * with the same name. + * + * @param obj the object to compare with this one. + * @return true if the object is an {@link MBeanPermission} + * with the same name. + */ + public boolean equals(Object obj) + { + if (obj instanceof MBeanServerPermission) + { + MBeanServerPermission o = (MBeanServerPermission) obj; + return o.getName().equals(getName()); + } + return false; + } + + /** + * Returns a unique hash code for this permission. + * This is simply the hashcode of {@link BasicPermission#getName()}. + * + * @return the hashcode of this permission. + */ + public int hashCode() + { + return getName().hashCode(); + } + + /** + * Returns true if this {@link MBeanServerPermission} implies + * the given permission. This occurs if the given permission + * is also an {@link MBeanServerPermission} and its target names + * are a subset of the target names of this permission. Note that + * the name <code>createMBeanServer</code> implies + * <code>newMBeanServer</code>. + * + * @param p the permission to check for implication. + * @return true if this permission implies <code>p</code>. + */ + public boolean implies(Permission p) + { + if (p instanceof MBeanServerPermission) + { + if (getName().equals("*")) + return true; + MBeanServerPermission msp = (MBeanServerPermission) p; + String[] thisCaps = getName().split(","); + String[] mspCaps = msp.getName().split(","); + for (int a = 0; a < mspCaps.length; ++a) + { + boolean found = false; + String mc = mspCaps[a].trim(); + for (int b = 0; b < thisCaps.length; ++b) + { + String tc = thisCaps[b].trim(); + if (tc.equals(mc)) + found = true; + if (tc.equals("createMBeanServer") && + mc.equals("newMBeanServer")) + found = true; + } + if (!found) + return false; + } + return true; + } + return false; + } + + /** + * Returns a {@link PermissionCollection} which stores + * a series of {@link MBeanServerPermission}s as the union + * of their capabilities. + * + * @return a collection for {@link MBeanServerPermission}s. + */ + public PermissionCollection newPermissionCollection() + { + return new MBeanServerPermissionCollection(); + } + + /** + * A collection of {@link MBeanServerPermission}s, stored + * as a single permission with the union of the capabilities + * as its capabilities. + * + * @author Andrew John Hughes (gnu...@me...) + * @since 1.5 + */ + private class MBeanServerPermissionCollection + extends PermissionCollection + { + + /** + * Compatible with JDK 1.5 + */ + private static final long serialVersionUID = -5661980843569388590L; + + /** + * The collected permission. This is <code>null</code> or + * the union of the permissions held by all the collected + * permissions. + */ + private MBeanServerPermission collectionPermission; + + /** + * Adds a new permission by unifying it with the existing + * collection permission. + * + * @param p the permission to add. + * @throws SecurityException if the collection is read only. + * @see #isReadOnly() + * @see #setReadOnly(boolean) + */ + public void add(Permission p) + { + if (isReadOnly()) + throw new SecurityException("This collection is read only."); + if (p instanceof MBeanServerPermission) + { + MBeanServerPermission msp = (MBeanServerPermission) p; + if (collectionPermission == null) + collectionPermission = msp; + else + { + String finalString = collectionPermission.getName(); + String[] cp = finalString.split(","); + String[] np = msp.getName().split(","); + int createms = finalString.indexOf("createMBeanServer"); + int newms = finalString.indexOf("newMBeanServer"); + for (int a = 0; a < np.length; ++a) + { + boolean found = false; + String nps = np[a].trim(); + for (int b = 0; b < cp.length; ++b) + { + String cps = cp[b].trim(); + if (cps.equals(nps)) + found = true; + if (np.equals("newMBeanServer") + && createms != -1) + found = true; + if (np.equals("createMBeanServer") + && newms != -1) + finalString.replace("newMBeanServer", + "createMBeanServer"); + } + if (!found) + finalString += "," + nps; + } + collectionPermission = + new MBeanServerPermission(finalString); + } + } + } + + /** + * Returns an enumeration over the single permission. + * + * @return an enumeration over the collection permission. + */ + public Enumeration elements() + { + return new + MBeanServerPermissionEnumeration(collectionPermission); + } + + /** + * Provides an enumeration over a comma-separated list + * of capabilities. + * + * @author Andrew John Hughes (gnu...@me...) + * @since 1.5 + */ + private class MBeanServerPermissionEnumeration + implements Enumeration + { + + /** + * The collected permission. + */ + private MBeanServerPermission p; + + /** + * True if we have returned the permission. + */ + private boolean done; + + /** + * Constructs a new {@link MBeanServerPermissionEnumeration} + * using the given collected permission. + * + * @param p the collected permission. + */ + public MBeanServerPermissionEnumeration(MBeanServerPermission p) + { + this.p = p; + done = false; + } + + /** + * Returns true if there are more capabilities to return. + * + * @return true if there are more capabilities available. + */ + public boolean hasMoreElements() + { + return !done; + } + + /** + * Returns the next capability. + * + * @return the next capability. + */ + public Object nextElement() + { + if (hasMoreElements()) + { + done = true; + return p; + } + else + throw new NoSuchElementException("No more elements are available."); + } + + } + + /** + * Returns true if the collected {@link MBeanServerPermission} + * implies the given permission. This occurs if the given permission + * is also an {@link MBeanServerPermission} and its target names + * are a subset of the target names of this permission. Note that + * the name <code>createMBeanServer</code> implies + * <code>newMBeanServer</code>. + * + * @param p the permission to check for implication. + * @return true if this permission implies <code>p</code>. + */ + public boolean implies(Permission p) + { + return collectionPermission.implies(p); + } + } + + /** + * Checks the name is valid, including removing + * the <code>newMBeanServer</code> permission when + * <code>createMBeanServer</code> is present. + * + * @param name the name to check. + * @throws NullPointerException if <code>name</code> + * is <code>null</code>. + * @throws IllegalArgumentException if <code>name</code> + * is not either equal to + * <code>"*"</code> or forms + * a comma-separated list of + * valid constraints. + */ + private static String checkName(String name) + { + if (!(name.equals("*"))) + { + String[] constraints = name.split(","); + name = ""; + boolean seenCreate = false; + boolean seenNew = false; + boolean start = true; + for (int a = 0; a < constraints.length; ++a) + { + String next = constraints[a].trim(); + if (!(next.equals("createMBeanServer") || + next.equals("findMBeanServer") || + next.equals("newMBeanServer") || + next.equals("releaseMBeanServer"))) + throw new IllegalArgumentException("An invalid constraint, " + + next + ", was specified."); + if (next.equals("newMBeanServer")) + seenNew = true; + else if (next.equals("createMBeanServer")) + seenCreate = true; + else + { + if (!start) + name += ","; + name += next; + start = false; + } + } + if (seenNew && !seenCreate) + name += (start ? "" : ",") + "newMBeanServer"; + else if (seenCreate) + name += (start ? "" : ",") + "createMBeanServer"; + } + return name; + } + +} + + + + Added: trunk/core/src/classpath/javax/javax/net/ssl/CertPathTrustManagerParameters.java =================================================================== --- trunk/core/src/classpath/javax/javax/net/ssl/CertPathTrustManagerParameters.java (rev 0) +++ trunk/core/src/classpath/javax/javax/net/ssl/CertPathTrustManagerParameters.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -0,0 +1,71 @@ +/* CertPathTrustManagerParameters.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.net.ssl; + +import java.security.cert.CertPathParameters; + +/** + * Trust manager parameters for certification paths. + */ +public class CertPathTrustManagerParameters implements ManagerFactoryParameters +{ + private final CertPathParameters params; + + /** + * Creates a new trust manager parameter instance. The argument is + * cloned to prevent modification of this instance. + * + * @param params The certificate path parameters. + * @throws NullPointerException If params is null. + */ + public CertPathTrustManagerParameters (final CertPathParameters params) + { + this.params = (CertPathParameters) params.clone (); + } + + /** + * Returns a copy of the certificate path parameters. + * + * @return A copy of the certificate path parameters. + */ + public CertPathParameters getParameters () + { + return (CertPathParameters) params.clone (); + } +} Modified: trunk/core/src/classpath/javax/javax/net/ssl/HandshakeCompletedEvent.java =================================================================== --- trunk/core/src/classpath/javax/javax/net/ssl/HandshakeCompletedEvent.java 2007-01-07 12:55:51 UTC (rev 3024) +++ trunk/core/src/classpath/javax/javax/net/ssl/HandshakeCompletedEvent.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -38,6 +38,7 @@ package javax.net.ssl; +import java.security.Principal; import java.security.cert.Certificate; import javax.security.cert.X509Certificate; @@ -108,6 +109,20 @@ } /** + * Returns the local identity used in this connection, or + * <code>null</code> if there is none. + * + * @return The local identity. + * @since 1.5 + */ + public Principal getLocalPrincipal () + { + if (session != null) + return session.getLocalPrincipal (); + return null; + } + + /** * Returns the peer's certificates being used in this connection. * * @return The peer's certificates. @@ -129,6 +144,22 @@ } /** + * Returns the peer's identity, or <code>null</code> if there is + * none. + * + * @return The peer's identity. + * @throws SSLPeerUnverifiedException If the remote peer's identity + * could not be verified. + * @since 1.5 + */ + public Principal getPeerPrincipal () throws SSLPeerUnverifiedException + { + if (session != null) + return session.getPeerPrincipal (); + return null; + } + + /** * Returns the SSL session object associated with this connection. * * @return The session object. Modified: trunk/core/src/classpath/javax/javax/net/ssl/HttpsURLConnection.java =================================================================== --- trunk/core/src/classpath/javax/javax/net/ssl/HttpsURLConnection.java 2007-01-07 12:55:51 UTC (rev 3024) +++ trunk/core/src/classpath/javax/javax/net/ssl/HttpsURLConnection.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -38,9 +38,12 @@ package javax.net.ssl; +import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; +import java.security.Principal; import java.security.cert.Certificate; +import java.security.cert.X509Certificate; /** * A URL connection that connects via the <i>Secure Socket Layer</i> @@ -245,6 +248,48 @@ this.factory = factory; } + /** + * Returns the local principal for this connection. + * + * <p>The default implementation will return the {@link + * javax.security.x500.X500Principal} for the end entity certificate + * in the local certificate chain if those certificates are of type + * {@link java.security.cert.X509Certificate}. Otherwise, this + * method returns <code>null</code>. + * + * @return The local principal. + * @since 1.5 + */ + public Principal getLocalPrincipal () + { + Certificate[] c = getLocalCertificates (); + if (c != null && c.length > 0 && (c[0] instanceof X509Certificate)) + return ((X509Certificate) c[0]).getSubjectX500Principal (); + return null; + } + + /** + * Returns the remote peer's principal for this connection. + * + * <p>The default implementation will return the {@link + * javax.security.x500.X500Principal} for the end entity certificate + * in the remote peer's certificate chain if those certificates are + * of type {@link java.security.cert.X509Certificate}. Otherwise, + * this method returns <code>null</code>. + * + * @return The remote principal. + * @throws SSLPeerUnverifiedException If the remote peer has not + * been verified. + * @since 1.5 + */ + public Principal getPeerPrincipal () throws SSLPeerUnverifiedException + { + Certificate[] c = getServerCertificates (); + if (c != null && c.length > 0 && (c[0] instanceof X509Certificate)) + return ((X509Certificate) c[0]).getSubjectX500Principal (); + return null; + } + // Abstract methods. // ------------------------------------------------------------------- Added: trunk/core/src/classpath/javax/javax/net/ssl/KeyStoreBuilderParameters.java =================================================================== --- trunk/core/src/classpath/javax/javax/net/ssl/KeyStoreBuilderParameters.java (rev 0) +++ trunk/core/src/classpath/javax/javax/net/ssl/KeyStoreBuilderParameters.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -0,0 +1,48 @@ +/* KeyStoreBuilderParameters.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.net.ssl; + +/** + * <p style="color: red;"><b>FIXME</b> this class is currently a stub; + * it depends on an implementation of {@link + * java.security.KeyStore.Builder}</p>. + */ +public class KeyStoreBuilderParameters implements ManagerFactoryParameters +{ +} Modified: trunk/core/src/classpath/javax/javax/net/ssl/SSLContext.java =================================================================== --- trunk/core/src/classpath/javax/javax/net/ssl/SSLContext.java 2007-01-07 12:55:51 UTC (rev 3024) +++ trunk/core/src/classpath/javax/javax/net/ssl/SSLContext.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -189,6 +189,31 @@ } /** + * Creates a new {@link SSLEngine} for this context. + * + * @return The new SSLEngine. + * @since 1.5 + */ + public final SSLEngine createSSLEngine () + { + return ctxSpi.engineCreateSSLEngine (); + } + + /** + * Creates a new {@link SSLEngine} for this context, with a given + * host name and port number. + * + * @param host The local host name. + * @param port The local port number. + * @return The new SSLEngine. + * @since 1.5 + */ + public final SSLEngine createSSLEngine (final String host, final int port) + { + return ctxSpi.engineCreateSSLEngine (host, port); + } + + /** * Returns the set of SSL contexts available for client connections. * * @return The set of SSL contexts available for client connections. Modified: trunk/core/src/classpath/javax/javax/net/ssl/SSLContextSpi.java =================================================================== --- trunk/core/src/classpath/javax/javax/net/ssl/SSLContextSpi.java 2007-01-07 12:55:51 UTC (rev 3024) +++ trunk/core/src/classpath/javax/javax/net/ssl/SSLContextSpi.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -64,7 +64,29 @@ // Abstract methods. // ------------------------------------------------------------------- + // Sun, you've broken existing applications by introducing new + // abstract methods! Goodjob!!! + /** + * Returns a new {@link SSLEngine} for this context. + * + * @return A new SSLEngine. + * @since 1.5 + */ + protected abstract SSLEngine engineCreateSSLEngine (); + + /** + * Returns a new {@link SSLEngine} for this context, for the given + * host name and port number. + * + * @param host The local host name. + * @param port The local port number. + * @return A new SSLEngine. + * @since 1.5 + */ + protected abstract SSLEngine engineCreateSSLEngine (String host, int port); + + /** * Returns the set of SSL sessions available for client connections. * * @return The set of SSL sessions available for client connections. Added: trunk/core/src/classpath/javax/javax/net/ssl/SSLEngine.java =================================================================== --- trunk/core/src/classpath/javax/javax/net/ssl/SSLEngine.java (rev 0) +++ trunk/core/src/classpath/javax/javax/net/ssl/SSLEngine.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -0,0 +1,442 @@ +/* SSLEngine.java -- advanced, generic utility for manipulating SSL messages. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.net.ssl; + +import java.nio.ByteBuffer; + +/** + * A class for low-level message wrapping and unwrapping of SSL + * messages. + * + * @author Casey Marshall (cs...@gn...) + * @since 1.5 + */ +public abstract class SSLEngine +{ + private final String peerHost; + private final int peerPort; + + /** + * Creates a new SSLEngine with no peer host name or port number. + */ + protected SSLEngine () + { + this (null, -1); + } + + /** + * Creates a new SSLEngine with the specified peer host name and + * port number. + * + * @param peerHost The peer's host name. + * @param peerPort The peer's port number. + */ + protected SSLEngine (String peerHost, int peerPort) + { + this.peerHost = peerHost; + this.peerPort = peerPort; + } + + + + /** + * Begin, or restart, the SSL handshake. + * + * @throws SSLException + */ + public abstract void beginHandshake () throws SSLException; + + /** + * Close the inbound state. + * + * @throws SSLException + */ + public abstract void closeInbound () throws SSLException; + + /** + * Close the outbound state. + */ + public abstract void closeOutbound (); + + /** + * + */ + public abstract Runnable getDelegatedTask (); + + /** + * Returns the peer host name this SSL session is connected to, or + * <code>null</code> if this value was not set. + * + * @return The peer host's name. + */ + public String getPeerHost () + { + return peerHost; + } + + /** + * Returns the peer IP port number this SSL session in communicating + * on, or -1 if this value was not set. + * + * @return The peer's port number. + */ + public int getPeerPort () + { + return peerPort; + } + + /** + * Returns a list of SSL cipher suite names this SSLEngine is + * configured to use. + * + * @return The list of enabled cipher suite names. + */ + public abstract String[] getEnabledCipherSuites(); + + /** + * Returns a list of SSL protocol version names this SSLEngine is + * configured to use. + * + * @return The list of enabled protocol names. + */ + public abstract String[] getEnabledProtocols (); + + /** + * Tells if sessions will be created by this engine, and therefore + * may be resumed at a later time. + * + * @return True if sessions will be created. + */ + public abstract boolean getEnableSessionCreation(); + + /** + * Return the current handshake status. + * + * @return The current handshake status. + */ + public abstract SSLEngineResult.HandshakeStatus getHandshakeStatus (); + + /** + * Tells if this SSLEngine is configured to require client + * authentication when in server mode. + * + * @return True iff client authentication is required. + */ + public abstract boolean getNeedClientAuth (); + + /** + * Return the {@link SSLSession} object this connection represents. + * + * @return The SSL session. + */ + public abstract SSLSession getSession (); + + /** + * Returns a list of SSL cipher suite names this SSLEngine + * implementation supports. + * + * @return The list of cipher suite names supported by this + * implementation. + */ + public abstract String[] getSupportedCipherSuites (); + + /** + * Returns a list of SSL protocol version names this SSLEngine + * implementation supports. SSL protocol names include things like + * "SSLv3" or "TLSv1". + * + * @return The list of SSL protocol names + */ + public abstract String[] getSupportedProtocols (); + + /** + * Tells if this SSLEngine is a "client" session. + * + * @return True iff this session is configured for client mode. + */ + public abstract boolean getUseClientMode (); + + /** + * Tells if client authentication is requested, but not required, + * for sessions in server mode. If true, a server session will + * request an authentication message from connecting clients, but + * will still allow clients to connect if they cannot be + * authenticated. + * + * @return True iff client authentication is requested. + */ + public abstract boolean getWantClientAuth (); + + /** + * Tells if the incoming data stream is finished, and thus if no + * more data will be available to be unwrapped. + * + * @return True if no more data is to be unwrapped. + */ + public abstract boolean isInboundDone (); + + /** + * Tells if the outgoing data stream is finished, and thus if no + * more data may be wrapped. + * + * @return True if no more data may be wrapped. + */ + public abstract boolean isOutboundDone (); + + /** + * Sets the list of enabled cipher suites. The argument is an array + * of strings of the canonical suite names. + * + * @param suites The cipher suites to enable. + * @throws IllegalArgumentException If any of the specified suite + * strings is not supported by this implementation, or if the + * argument is null. + */ + public abstract void setEnabledCipherSuites (String[] suites); + + /** + * Sets the list of enabled protocol versions. The argument is an + * array of strings of the canonical protocol version names, such as + * "TLSv1". + * + * @param protocols The protocol versions to enable. + * @throws IllegalArgumentException If any of the specified + * protocols are not supported, or if the argument is null. + */ + public abstract void setEnabledProtocols (String[] protocols); + + /** + * Enables or disables session creation. If enabled, each connection + * will create session that may be resumed by another connection. + * + * @param create Whether or not to enable session creation. + */ + public abstract void setEnableSessionCreation (boolean create); + + /** + * Enables client or server mode. If the argument is true, this + * engine will run in client mode; if false, server mode. + * + * @param clientMode Whether or not to use client mode. + */ + public abstract void setUseClientMode (boolean clientMode); + + /** + * Enables or disables required client authentication. If enabled, + * clients may only connect if they provide proper identification. + * + * <p>This parameter is only used in server mode. + * + * @param needAuth Whether or not client authentication is required. + */ + public abstract void setNeedClientAuth (boolean needAuth); + + /** + * Enables or disables requested client authentication. If enabled, + * clients will be asked to provide proper identification, but will + * still be allowed to connect if they do not provide it. + * + * <p>This parameter is only used in server mode. + * + * @param wantAuth Whether or not client authentication will be + * requested, but not required. + */ + public abstract void setWantClientAuth (boolean wantAuth); + + /** + * Unwraps a byte buffer recieved from the network, storing the + * decrypted, unwrapped bytes into the given buffer. + * + * <p>This call is exactly equivalent to <code>unwrap (source, new + * ByteBuffer[] { sink }, 0, 1)</code>. + * + * @param source The source bytes, coming from the network. + * @param sink The buffer to hold the unwrapped message. + * @return An engine result object for the operation. + * @throws SSLException If an SSL message parsing error occurs. + * @throws java.nio.ReadOnlyBufferException If 'sink' is not + * writable. + * @throws IllegalArgumentException If either 'source' or 'sink' is + * null. + * @throws IllegalStateException If this engine has not been put + * into client or server mode. + */ + public SSLEngineResult unwrap (ByteBuffer source, ByteBuffer sink) + throws SSLException + { + return unwrap (source, new ByteBuffer[] { sink }, 0, 1); + } + + /** + * Unwraps a byte buffer recieved from the network, storing the + * decrypted, unwrapped bytes into the given buffers. + * + * <p>This call is exactly equivalent to <code>unwrap (source, + * sinks, 0, sinks.length)</code>. + * + * @param source The source bytes, coming from the network. + * @param sinks The buffers to hold the unwrapped message. + * @return An engine result object for the operation. + * @throws SSLException If an SSL message parsing error occurs. + * @throws java.nio.ReadOnlyBufferException If any buffer in 'sinks' + * is not writable. + * @throws IllegalArgumentException If either 'source' or 'sinks' is + * null. + * @throws IllegalStateException If this engine has not been put + * into client or server mode. + */ + public SSLEngineResult unwrap (ByteBuffer source, ByteBuffer[] sinks) + throws SSLException + { + return unwrap (source, sinks, 0, sinks.length); + } + + /** + * Unwraps a byte buffer received from the network, storing the + * decrypted, unwrapped bytes into the given buffers. After + * unwrapping, the bytes placed into the sink buffers are ready for + * consumption by the application. + * + * <p>This method may place no bytes in the destination buffer; for + * example, if this engine is still performing the SSL handshake, + * only handshake data will be consumed, and no application data. + * + * <p>It is stated that this method may modify the source buffer, + * and that it must not be passed to another SSLEngine (SSL + * connections are independent, so another SSLEngine will not have + * the parameters or state to handle messages meant for this + * engine). + * + * @param source The source bytes, coming from the network. + * @param sinks The buffers to hold the unwrapped message. + * @param offset The index of the first buffer in 'sinks' to use. + * @param length The number of buffers in 'sinks' to use. + * @return An engine result object for the operation. + * @throws SSLException If an SSL message parsing error occurs. + * @throws java.nio.ReadOnlyBufferException If any buffer in 'sinks' + * is not writable. + * @throws IllegalArgumentException If either 'source' or 'sinks' is + * null. + * @throws IllegalStateException If this engine has not been put + * into client or server mode. + * @throws IndexOutOfBoundsException If 'offset' or 'length' is + * negative, or if 'length+offset' is greater than 'sinks.length'. + */ + public abstract SSLEngineResult unwrap (ByteBuffer source, + ByteBuffer[] sinks, int offset, + int length) + throws javax.net.ssl.SSLException; + + /** + * Wraps a byte buffer into an SSL message, for preparation to send + * it over the network. + * + * <p>This method is exactly equivalent to <code>wrap (new + * ByteBuffer[] { source }, 0, 1, sink)</code>. + * + * @param source The source buffer with application data. + * @param sink The buffer to hold the wrapped data. + * @return An engine result object for the operation. + * @throws SSLException If an SSL error occurs. + * @throws java.nio.ReadOnlyBufferException If 'sink' is read-only. + * @throws IllegalArgumentException If either 'source' or 'sink' is + * null. + * @throws IllegalStateException If this engine has not been put + * into client or server mode. + */ + public SSLEngineResult wrap (ByteBuffer source, ByteBuffer sink) + throws SSLException + { + return wrap (new ByteBuffer[] { source }, 0, 1, sink); + } + + /** + * Wraps byte buffers into an SSL message, for preparation to send + * them over the network. + * + * <p>This method is exactly equivalent to <code>wrap (sources, 0, + * 1, sink)</code>. + * + * @param sources The source buffers with application data. + * @param sink The buffer to hold the wrapped data. + * @return An engine result object for the operation. + * @throws SSLException If an SSL error occurs. + * @throws java.nio.ReadOnlyBufferException If 'sink' is read-only. + * @throws IllegalArgumentException If either 'sources' or 'sink' is + * null. + * @throws IllegalStateException If this engine has not been put + * into client or server mode. + */ + public SSLEngineResult wrap (ByteBuffer[] sources, ByteBuffer sink) + throws SSLException + { + return wrap (sources, 0, sources.length, sink); + } + + /** + * Wraps byte buffers into an SSL message, for preparation to send + * them over the network. After wrapping, the data in the sink + * buffer is ready to be sent over the transport layer. + * + * <p>This method may consume no data from the source buffers, and + * yet still produce output that should be sent accross the wire; + * for example if this engine has not yet completed the SSL + * handshake, the sink buffer will be filled with handshake + * messages. + * + * @param sources The source buffers with application data. + * @param offset The offset into the source buffers to start reading + * application data. + * @param length The number of buffers to read from 'sources'. + * @param sink The buffer to hold the wrapped data. + * @return An engine result object for the operation. + * @throws SSLException If an SSL error occurs. + * @throws java.nio.ReadOnlyBufferException If 'sink' is read-only. + * @throws IllegalArgumentException If either 'sources' or 'sink' is + * null. + * @throws IllegalStateException If this engine has not been put + * into client or server mode. + * @throws IndexOutOfBoundsException If 'offset' or 'length' is + * negative, or if 'length+offset' is greater than 'sources.length'. + */ + public abstract SSLEngineResult wrap (ByteBuffer[] sources, int offset, + int length, ByteBuffer sink) + throws SSLException; + +} Added: trunk/core/src/classpath/javax/javax/net/ssl/SSLEngineResult.java =================================================================== --- trunk/core/src/classpath/javax/javax/net/ssl/SSLEngineResult.java (rev 0) +++ trunk/core/src/classpath/javax/javax/net/ssl/SSLEngineResult.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -0,0 +1,194 @@ +/* SSLEngineResult.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.net.ssl; + +/** + * A result from an {@link SSLEngine} <code>wrap</code> or + * <code>unwrap</code> operation. This class conveys a possibly + * intermediate result, and may ask for more input data or request + * that output data be sent over a connection. + */ +public class SSLEngineResult +{ + private final HandshakeStatus handshakeStatus; + private final Status status; + private final int bytesConsumed; + private final int bytesProduced; + + /** + * Creates a new SSL engine result. + * + * @param status The status of the SSL connection. + * @param handshakeStatus The status of the SSL handshake. + * @param bytesConsumed The number of bytes consumed by the previous + * operation. + * @param bytesProduced The number of bytes produced by the previous + * operation. + * @throws IllegalArgumentException If either enum value is + * <code>null</code>, or if either integer is negative. + */ + public SSLEngineResult (Status status, HandshakeStatus handshakeStatus, + int bytesConsumed, int bytesProduced) + { + if (status == null) + throw new IllegalArgumentException ("'status' may not be null"); + if (handshakeStatus == null) + throw new IllegalArgumentException ("'handshakeStatus' may not be null"); + if (bytesConsumed < 0) + throw new IllegalArgumentException ("'bytesConumed' must be nonnegative"); + if (bytesProduced < 0) + throw new IllegalArgumentException ("'bytesProduced' must be nonnegative"); + this.status = status; + this.handshakeStatus = handshakeStatus; + this.bytesConsumed = bytesConsumed; + this.bytesProduced = bytesProduced; + } + + + + /** + * An enumeration of possible general states. + */ + public static enum Status + { + + /** + * There were not enough input bytes available to complete the + * operation. + */ + BUFFER_UNDERFLOW, + + /** + * There was not enough space for the output message. + */ + BUFFER_OVERFLOW, + + /** + * Okay. No error. + */ + OK, + + /** + * The connection is closed. + */ + CLOSED + } + + /** + * An enumeration of possible handshake status states. + */ + public static enum HandshakeStatus + { + + /** + * Not currently handshaking. + */ + NOT_HANDSHAKING, + + /** + * The handshake is finished. + */ + FINISHED, + + /** + * Needs the status of one or more delegated tasks. + */ + NEED_TASK, + + /** + * Has data prepared for output, and needs a new call to + * <code>wrap</code>. + */ + NEED_WRAP, + + /** + * Is waiting for more input. + */ + NEED_UNWRAP + } + + + + /** + * Returns the number of bytes consumed by the previous operation. + * + * @return The number of bytes consumed. + */ + public int bytesConsumed () + { + return bytesConsumed; + } + + /** + * Returns the number of bytes produced by the previous operation. + * + * @return The number of bytes produced. + */ + public int bytesProduced () + { + return bytesProduced; + } + + /** + * Returns the handshake status. + * + * @return The handshake status. + */ + public HandshakeStatus getHandshakeStatus () + { + return handshakeStatus; + } + + /** + * Returns the connection status. + * + * @return The connection status. + */ + public Status getStatus () + { + return status; + } + + public String toString () + { + return (super.toString () + " [ status: " + status + "; handshakeStatus: " + + handshakeStatus + "; bytesConsumed: " + bytesConsumed + + "; bytesProduced: " + bytesProduced + " ]"); + } +} Modified: trunk/core/src/classpath/javax/javax/net/ssl/SSLServerSocketFactory.java =================================================================== --- trunk/core/src/classpath/javax/javax/net/ssl/SSLServerSocketFactory.java 2007-01-07 12:55:51 UTC (rev 3024) +++ trunk/core/src/classpath/javax/javax/net/ssl/SSLServerSocketFactory.java 2007-01-07 12:57:57 UTC (rev 3025) @@ -38,6 +38,9 @@ package javax.net.ssl; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; import java.security.KeyStore; import java.security.Security; @@ -138,8 +141,9 @@ } catch (Exception ex) { - throw new RuntimeException("error instantiating default server socket factory: " - + ex.toString()); + return ne... [truncated message content] |
From: <ls...@us...> - 2007-01-07 12:55:52
|
Revision: 3024 http://jnode.svn.sourceforge.net/jnode/?rev=3024&view=rev Author: lsantha Date: 2007-01-07 04:55:51 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/javax/javax/print/PrintService.java trunk/core/src/classpath/javax/javax/print/attribute/Attribute.java trunk/core/src/classpath/javax/javax/print/attribute/AttributeSet.java trunk/core/src/classpath/javax/javax/print/attribute/AttributeSetUtilities.java trunk/core/src/classpath/javax/javax/print/attribute/HashAttributeSet.java trunk/core/src/classpath/javax/javax/print/attribute/standard/Chromaticity.java trunk/core/src/classpath/javax/javax/print/attribute/standard/ColorSupported.java trunk/core/src/classpath/javax/javax/print/attribute/standard/Compression.java trunk/core/src/classpath/javax/javax/print/attribute/standard/Copies.java trunk/core/src/classpath/javax/javax/print/attribute/standard/CopiesSupported.java trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtCompleted.java trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtCreation.java trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtProcessing.java trunk/core/src/classpath/javax/javax/print/attribute/standard/Destination.java trunk/core/src/classpath/javax/javax/print/attribute/standard/DocumentName.java trunk/core/src/classpath/javax/javax/print/attribute/standard/Fidelity.java trunk/core/src/classpath/javax/javax/print/attribute/standard/Finishings.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobHoldUntil.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressions.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressionsCompleted.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressionsSupported.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctets.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctetsProcessed.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctetsSupported.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheets.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheetsCompleted.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheetsSupported.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMessageFromOperator.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobName.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobOriginatingUserName.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobPriority.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobPrioritySupported.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobSheets.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobState.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobStateReason.java trunk/core/src/classpath/javax/javax/print/attribute/standard/JobStateReasons.java trunk/core/src/classpath/javax/javax/print/attribute/standard/Media.java trunk/core/src/classpath/javax/javax/print/attribute/standard/MediaPrintableArea.java trunk/core/src/classpath/javax/javax/print/attribute/standard/MediaSize.java trunk/core/src/classpath/javax/javax/print/attribute/standard/MultipleDocumentHandling.java trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberOfDocuments.java trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberOfInterveningJobs.java trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberUp.java trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberUpSupported.java trunk/core/src/classpath/javax/javax/print/attribute/standard/OrientationRequested.java trunk/core/src/classpath/javax/javax/print/attribute/standard/OutputDeviceAssigned.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PDLOverrideSupported.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PageRanges.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PagesPerMinute.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PagesPerMinuteColor.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PresentationDirection.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrintQuality.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterInfo.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterIsAcceptingJobs.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterLocation.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMakeAndModel.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMessageFromOperator.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMoreInfo.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMoreInfoManufacturer.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterName.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterResolution.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterState.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterStateReason.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterStateReasons.java trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterURI.java trunk/core/src/classpath/javax/javax/print/attribute/standard/QueuedJobCount.java trunk/core/src/classpath/javax/javax/print/attribute/standard/ReferenceUriSchemesSupported.java trunk/core/src/classpath/javax/javax/print/attribute/standard/RequestingUserName.java trunk/core/src/classpath/javax/javax/print/attribute/standard/Severity.java trunk/core/src/classpath/javax/javax/print/attribute/standard/SheetCollate.java trunk/core/src/classpath/javax/javax/print/attribute/standard/Sides.java Modified: trunk/core/src/classpath/javax/javax/print/PrintService.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/PrintService.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/PrintService.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -89,7 +89,7 @@ * @throws IllegalArgumentException if category is not a class that * implements <code>PrintServiceAttribute</code>. */ - PrintServiceAttribute getAttribute(Class category); + <T extends PrintServiceAttribute> T getAttribute(Class<T> category); /** * Returns the attributes describing this print service. The returned @@ -123,7 +123,7 @@ * @throws IllegalArgumentException if <code>category</code> is a class * not implementing <code>Attribute</code> */ - Object getDefaultAttributeValue(Class category); + Object getDefaultAttributeValue(Class<? extends Attribute> category); /** * Returns the name of this print service. @@ -145,7 +145,7 @@ * * @return The class array of all supported attribute categories. */ - Class[] getSupportedAttributeCategories(); + Class<?>[] getSupportedAttributeCategories(); /** * Determines and returns all supported attribute values of a given @@ -177,7 +177,9 @@ * implementing <code>Attribute</code>, or if <code>flavor</code> is not * supported */ - Object getSupportedAttributeValues(Class category, DocFlavor flavor, AttributeSet attributes); + Object getSupportedAttributeValues(Class<? extends Attribute> category, + DocFlavor flavor, + AttributeSet attributes); /** * Determines and returns an array of all supported document flavors which @@ -189,7 +191,7 @@ * the specific doc flavor and attributes set. * </p> * - * @return The supported document flavors. + * @return the supported document flavors */ DocFlavor[] getSupportedDocFlavors(); @@ -240,7 +242,7 @@ * @throws IllegalArgumentException if <code>category</code> is a class not * implementing <code>Attribute</code>. */ - boolean isAttributeCategorySupported(Class category); + boolean isAttributeCategorySupported(Class<? extends Attribute> category); /** * Determines if a given attribute value is supported when creating a print Modified: trunk/core/src/classpath/javax/javax/print/attribute/Attribute.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/Attribute.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/Attribute.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -52,7 +52,7 @@ * * @return The concrete {@link Class} instance of the attribute class. */ - Class getCategory (); + Class< ? extends Attribute> getCategory (); /** * Returns the descriptive name of the attribute category. Modified: trunk/core/src/classpath/javax/javax/print/attribute/AttributeSet.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/AttributeSet.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/AttributeSet.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -110,7 +110,7 @@ * @return <code>true</code> if an attribute of the category is contained * in the set, <code>false</code> otherwise. */ - boolean containsKey (Class category); + boolean containsKey (Class<?> category); /** * Checks if this attribute set contains the given attribute. @@ -143,7 +143,7 @@ * @throws ClassCastException if category is not implementing * <code>Attribute</code>. */ - Attribute get (Class category); + Attribute get (Class<?> category); /** * Returns the hashcode value. The hashcode value is the sum of all hashcodes @@ -178,7 +178,7 @@ * @return <code>true</code> if an attribute is removed, false in all other cases. * @throws UnmodifiableSetException if the set does not support modification. */ - boolean remove (Class category); + boolean remove (Class<?> category); /** * Returns the number of elements in this attribute set. Modified: trunk/core/src/classpath/javax/javax/print/attribute/AttributeSetUtilities.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/AttributeSetUtilities.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/AttributeSetUtilities.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -435,8 +435,8 @@ * that implements interfaceName * @exception NullPointerException if object is null */ - public static Class verifyAttributeCategory(Object object, - Class interfaceName) + public static Class<?> verifyAttributeCategory(Object object, + Class<?> interfaceName) { if (object == null) throw new NullPointerException("object may not be null"); @@ -461,7 +461,7 @@ * @exception NullPointerException if object is null */ public static Attribute verifyAttributeValue(Object object, - Class interfaceName) + Class<?> interfaceName) { if (object == null) throw new NullPointerException("object may not be null"); @@ -482,7 +482,7 @@ * @exception IllegalArgumentException if the categories are not equal * @exception NullPointerException if category is null */ - public static void verifyCategoryForValue(Class category, + public static void verifyCategoryForValue(Class<?> category, Attribute attribute) { if (category == null || attribute == null) Modified: trunk/core/src/classpath/javax/javax/print/attribute/HashAttributeSet.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/HashAttributeSet.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/HashAttributeSet.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -110,7 +110,7 @@ * * @exception NullPointerException if interfaceName is null */ - protected HashAttributeSet(Class interfaceName) + protected HashAttributeSet(Class<?> interfaceName) { if (interfaceName == null) throw new NullPointerException("interfaceName may not be null"); @@ -129,7 +129,7 @@ * interfaceName * @exception NullPointerException if attribute or interfaceName is null */ - protected HashAttributeSet(Attribute attribute, Class interfaceName) + protected HashAttributeSet(Attribute attribute, Class<?> interfaceName) { this(interfaceName); @@ -151,7 +151,7 @@ * interface of interfaceName * @exception NullPointerException if attributes or interfaceName is null */ - protected HashAttributeSet(Attribute[] attributes, Class interfaceName) + protected HashAttributeSet(Attribute[] attributes, Class<?> interfaceName) { this(interfaceName); @@ -173,7 +173,7 @@ * @exception ClassCastException if any element of attributes is not an * interface of interfaceName */ - protected HashAttributeSet(AttributeSet attributes, Class interfaceName) + protected HashAttributeSet(AttributeSet attributes, Class<?> interfaceName) { this(interfaceName); @@ -256,7 +256,7 @@ * @return <code>true</code> if an attribute of the category is contained * in the set, <code>false</code> otherwise. */ - public boolean containsKey(Class category) + public boolean containsKey(Class<?> category) { return attributeMap.containsKey(category); } @@ -301,7 +301,7 @@ * @throws ClassCastException if category is not implementing * <code>Attribute</code>. */ - public Attribute get(Class category) + public Attribute get(Class<?> category) { if (category == null) throw new NullPointerException("category may not be null"); @@ -359,7 +359,7 @@ * @return <code>true</code> if an attribute is removed, false in all other cases. * @throws UnmodifiableSetException if the set does not support modification. */ - public boolean remove(Class category) + public boolean remove(Class<?> category) { if (category == null) return false; Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/Chromaticity.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/Chromaticity.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/Chromaticity.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -38,6 +38,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.DocAttribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintJobAttribute; @@ -94,7 +95,7 @@ * * @return The class <code>Chromaticity</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return Chromaticity.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/ColorSupported.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/ColorSupported.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/ColorSupported.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintServiceAttribute; @@ -88,7 +89,7 @@ * * @return The class <code>ColorSupported</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return ColorSupported.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/Compression.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/Compression.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/Compression.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.DocAttribute; import javax.print.attribute.EnumSyntax; @@ -91,7 +92,7 @@ * * @return The class <code>Compression</code> itself. */ - public final Class getCategory() + public Class< ? extends Attribute> getCategory() { return Compression.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/Copies.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/Copies.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/Copies.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -97,7 +98,7 @@ * * @return The class <code>Copies</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return Copies.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/CopiesSupported.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/CopiesSupported.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/CopiesSupported.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.SetOfIntegerSyntax; import javax.print.attribute.SupportedValuesAttribute; @@ -112,7 +113,7 @@ * * @return The class <code>CopiesSupported</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return CopiesSupported.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtCompleted.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtCompleted.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtCompleted.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Date; +import javax.print.attribute.Attribute; import javax.print.attribute.DateTimeSyntax; import javax.print.attribute.PrintJobAttribute; @@ -92,7 +93,7 @@ * * @return The class <code>DateTimeAtCompleted</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return DateTimeAtCompleted.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtCreation.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtCreation.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtCreation.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Date; +import javax.print.attribute.Attribute; import javax.print.attribute.DateTimeSyntax; import javax.print.attribute.PrintJobAttribute; @@ -92,7 +93,7 @@ * * @return The class <code>DateTimeAtCreation</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return DateTimeAtCreation.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtProcessing.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtProcessing.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/DateTimeAtProcessing.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Date; +import javax.print.attribute.Attribute; import javax.print.attribute.DateTimeSyntax; import javax.print.attribute.PrintJobAttribute; @@ -92,7 +93,7 @@ * * @return The class <code>DateTimeAtProcessing</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return DateTimeAtProcessing.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/Destination.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/Destination.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/Destination.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.net.URI; +import javax.print.attribute.Attribute; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; import javax.print.attribute.URISyntax; @@ -104,7 +105,7 @@ * * @return The class <code>Destination</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return Destination.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/DocumentName.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/DocumentName.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/DocumentName.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Locale; +import javax.print.attribute.Attribute; import javax.print.attribute.DocAttribute; import javax.print.attribute.TextSyntax; @@ -98,7 +99,7 @@ * * @return The class <code>DocumentName</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return DocumentName.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/Fidelity.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/Fidelity.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/Fidelity.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -38,6 +38,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -107,7 +108,7 @@ * * @return The class <code>Fidelity</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return Fidelity.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/Finishings.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/Finishings.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/Finishings.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -38,6 +38,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.DocAttribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintJobAttribute; @@ -238,7 +239,7 @@ * * @return the class <code>Finishings</code> itself */ - public final Class getCategory() + public Class< ? extends Attribute> getCategory() { return Finishings.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobHoldUntil.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobHoldUntil.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobHoldUntil.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Date; +import javax.print.attribute.Attribute; import javax.print.attribute.DateTimeSyntax; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -98,7 +99,7 @@ * * @return The class <code>JobHoldUntil</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobHoldUntil.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressions.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressions.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressions.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -110,7 +111,7 @@ * * @return The class <code>JobImpressions</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobImpressions.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressionsCompleted.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressionsCompleted.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressionsCompleted.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintJobAttribute; @@ -101,7 +102,7 @@ * * @return The class <code>JobImpressionsCompleted</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobImpressionsCompleted.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressionsSupported.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressionsSupported.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobImpressionsSupported.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.SetOfIntegerSyntax; import javax.print.attribute.SupportedValuesAttribute; @@ -96,7 +97,7 @@ * * @return The class <code>JobImpressionsSupported</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobImpressionsSupported.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctets.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctets.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctets.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -110,7 +111,7 @@ * * @return The class <code>JobKOctets</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobKOctets.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctetsProcessed.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctetsProcessed.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctetsProcessed.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintJobAttribute; @@ -102,7 +103,7 @@ * * @return The class <code>JobKOctetsProcessed</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobKOctetsProcessed.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctetsSupported.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctetsSupported.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobKOctetsSupported.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.SetOfIntegerSyntax; import javax.print.attribute.SupportedValuesAttribute; @@ -96,7 +97,7 @@ * * @return The class <code>JobKOctetsSupported</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobKOctetsSupported.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheets.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheets.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheets.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -107,7 +108,7 @@ * * @return The class <code>JobMediaSheets</code> itself. */ - public final Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobMediaSheets.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheetsCompleted.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheetsCompleted.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheetsCompleted.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintJobAttribute; @@ -96,7 +97,7 @@ * * @return The class <code>JobMediaSheetsCompleted</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobMediaSheetsCompleted.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheetsSupported.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheetsSupported.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMediaSheetsSupported.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.SetOfIntegerSyntax; import javax.print.attribute.SupportedValuesAttribute; @@ -96,7 +97,7 @@ * * @return The class <code>JobMediaSheetsSupported</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobMediaSheetsSupported.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMessageFromOperator.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMessageFromOperator.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobMessageFromOperator.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Locale; +import javax.print.attribute.Attribute; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.TextSyntax; @@ -95,7 +96,7 @@ * * @return The class <code>JobMessageFromOperator</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobMessageFromOperator.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobName.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobName.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobName.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Locale; +import javax.print.attribute.Attribute; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; import javax.print.attribute.TextSyntax; @@ -93,7 +94,7 @@ * * @return The class <code>JobName</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobName.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobOriginatingUserName.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobOriginatingUserName.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobOriginatingUserName.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Locale; +import javax.print.attribute.Attribute; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.TextSyntax; @@ -92,7 +93,7 @@ * * @return The class <code>JobOriginatingUserName</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobOriginatingUserName.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobPriority.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobPriority.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobPriority.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -97,7 +98,7 @@ * * @return The class <code>JobPriority</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobPriority.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobPrioritySupported.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobPrioritySupported.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobPrioritySupported.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.SupportedValuesAttribute; @@ -99,7 +100,7 @@ * * @return The class <code>JobPrioritySupported</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobPrioritySupported.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobSheets.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobSheets.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobSheets.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -88,7 +89,7 @@ * * @return The class <code>JobSheets</code> itself. */ - public final Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobSheets.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobState.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobState.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobState.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintJobAttribute; @@ -137,7 +138,7 @@ * * @return The class <code>JobState</code> itself. */ - public final Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobState.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobStateReason.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobStateReason.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobStateReason.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -262,7 +262,7 @@ * * @return The class <code>JobStateReason</code> itself. */ - public final Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobStateReason.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/JobStateReasons.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/JobStateReasons.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/JobStateReasons.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -42,6 +42,7 @@ import java.util.HashSet; import java.util.Iterator; +import javax.print.attribute.Attribute; import javax.print.attribute.PrintJobAttribute; /** @@ -56,7 +57,7 @@ * @author Michael Koch (kon...@gm...) * @author Wolfgang Baer (WB...@gm...) */ -public final class JobStateReasons extends HashSet +public final class JobStateReasons extends HashSet<JobStateReason> implements PrintJobAttribute { private static final long serialVersionUID = 8849088261264331812L; @@ -108,12 +109,11 @@ * @throws ClassCastException if values of collection are not of type * <code>JobStateReason</code>. */ - public JobStateReasons(Collection collection) + public JobStateReasons(Collection<JobStateReason> collection) { super(collection.size(), 0.75f); - Iterator it = collection.iterator(); - while (it.hasNext()) - add(it.next()); + for (JobStateReason reason : collection) + add(reason); } /** @@ -126,12 +126,12 @@ * @throws ClassCastException if given object is not an instance of * <code>JobStateReason</code>. */ - public boolean add(Object o) + public boolean add(JobStateReason o) { if (o == null) throw new NullPointerException("reason is null"); - return super.add((JobStateReason) o); + return add(o); } /** @@ -139,7 +139,7 @@ * * @return The class <code>JobStateReasons</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return JobStateReasons.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/Media.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/Media.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/Media.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.DocAttribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintJobAttribute; @@ -105,7 +106,7 @@ * * @return The class <code>Media</code> itself. */ - public final Class getCategory() + public Class< ? extends Attribute> getCategory() { return Media.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/MediaPrintableArea.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/MediaPrintableArea.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/MediaPrintableArea.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -38,6 +38,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.DocAttribute; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -152,7 +153,7 @@ * * @return The class <code>MediaPrintableArea</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return MediaPrintableArea.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/MediaSize.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/MediaSize.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/MediaSize.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -67,11 +67,11 @@ { private static final long serialVersionUID = -1967958664615414771L; - private static ArrayList mediaCache; + private static ArrayList<MediaSize> mediaCache; static { - mediaCache = new ArrayList(); + mediaCache = new ArrayList<MediaSize>(); // We call one instance of every container class to make sure it gets // loaded during class initialization and therefore all other static @@ -180,11 +180,12 @@ * * @return The class <code>MediaSize</code> itself. */ - public final Class getCategory() + public Class< ? extends Attribute> getCategory() { return MediaSize.class; } + /** * Searches for a MediaSize object with the given dimensions. * If none is found with exact dimensions, the closest match is used. Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/MultipleDocumentHandling.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/MultipleDocumentHandling.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/MultipleDocumentHandling.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -108,7 +109,7 @@ * * @return The class <code>MultipleDocumentHandling</code> itself. */ - public final Class getCategory() + public Class< ? extends Attribute> getCategory() { return MultipleDocumentHandling.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberOfDocuments.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberOfDocuments.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberOfDocuments.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintJobAttribute; @@ -90,7 +91,7 @@ * * @return The class <code>NumberOfDocuments</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return NumberOfDocuments.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberOfInterveningJobs.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberOfInterveningJobs.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberOfInterveningJobs.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintJobAttribute; @@ -91,7 +92,7 @@ * * @return The class <code>NumberOfInterveningJobs</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return NumberOfInterveningJobs.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberUp.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberUp.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberUp.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.DocAttribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintJobAttribute; @@ -95,7 +96,7 @@ * * @return The class <code>NumberUp</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return NumberUp.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberUpSupported.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberUpSupported.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/NumberUpSupported.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.SetOfIntegerSyntax; import javax.print.attribute.SupportedValuesAttribute; @@ -128,7 +129,7 @@ * * @return The class <code>NumberUpSupported</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return NumberUpSupported.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/OrientationRequested.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/OrientationRequested.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/OrientationRequested.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.DocAttribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintJobAttribute; @@ -112,7 +113,7 @@ * * @return The class <code>OrientationRequested</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return OrientationRequested.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/OutputDeviceAssigned.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/OutputDeviceAssigned.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/OutputDeviceAssigned.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Locale; +import javax.print.attribute.Attribute; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.TextSyntax; @@ -98,7 +99,7 @@ * * @return The class <code>OutputDeviceAssigned</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return OutputDeviceAssigned.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PDLOverrideSupported.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PDLOverrideSupported.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PDLOverrideSupported.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintServiceAttribute; @@ -91,7 +92,7 @@ * * @return The class <code>PDLOverrideSupported</code> itself. */ - public final Class getCategory() + public Class< ? extends Attribute> getCategory() { return PDLOverrideSupported.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PageRanges.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PageRanges.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PageRanges.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -38,6 +38,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.DocAttribute; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -154,7 +155,7 @@ * * @return The class <code>PageRanges</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return PageRanges.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PagesPerMinute.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PagesPerMinute.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PagesPerMinute.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -38,6 +38,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintServiceAttribute; @@ -92,7 +93,7 @@ * * @return The class <code>PagesPerMinute</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return PagesPerMinute.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PagesPerMinuteColor.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PagesPerMinuteColor.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PagesPerMinuteColor.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.IntegerSyntax; import javax.print.attribute.PrintServiceAttribute; @@ -91,7 +92,7 @@ * * @return The class <code>PagesPerMinuteColor</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return PagesPerMinuteColor.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PresentationDirection.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PresentationDirection.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PresentationDirection.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintRequestAttribute; @@ -138,7 +139,7 @@ * * @return The class <code>PresentationDirection</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return PresentationDirection.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PrintQuality.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PrintQuality.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PrintQuality.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.DocAttribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintJobAttribute; @@ -92,7 +93,7 @@ * * @return The class <code>PrintQuality</code> itself. */ - public final Class getCategory() + public Class< ? extends Attribute> getCategory() { return PrintQuality.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterInfo.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterInfo.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterInfo.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Locale; +import javax.print.attribute.Attribute; import javax.print.attribute.PrintServiceAttribute; import javax.print.attribute.TextSyntax; @@ -92,7 +93,7 @@ * * @return The class <code>PrinterInfo</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return PrinterInfo.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterIsAcceptingJobs.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterIsAcceptingJobs.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterIsAcceptingJobs.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -37,6 +37,7 @@ package javax.print.attribute.standard; +import javax.print.attribute.Attribute; import javax.print.attribute.EnumSyntax; import javax.print.attribute.PrintServiceAttribute; @@ -93,7 +94,7 @@ * * @return The class <code>PrinterIsAcceptingJobs</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return PrinterIsAcceptingJobs.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterLocation.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterLocation.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterLocation.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Locale; +import javax.print.attribute.Attribute; import javax.print.attribute.PrintServiceAttribute; import javax.print.attribute.TextSyntax; @@ -92,7 +93,7 @@ * * @return The class <code>PrinterLocation</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return PrinterLocation.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMakeAndModel.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMakeAndModel.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMakeAndModel.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Locale; +import javax.print.attribute.Attribute; import javax.print.attribute.PrintServiceAttribute; import javax.print.attribute.TextSyntax; @@ -92,7 +93,7 @@ * * @return The class <code>PrinterMakeAndModel</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return PrinterMakeAndModel.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMessageFromOperator.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMessageFromOperator.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMessageFromOperator.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.util.Locale; +import javax.print.attribute.Attribute; import javax.print.attribute.PrintServiceAttribute; import javax.print.attribute.TextSyntax; @@ -95,7 +96,7 @@ * * @return The class <code>PrinterMessageFromOperator</code> itself. */ - public Class getCategory() + public Class< ? extends Attribute> getCategory() { return PrinterMessageFromOperator.class; } Modified: trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMoreInfo.java =================================================================== --- trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMoreInfo.java 2007-01-07 12:54:15 UTC (rev 3023) +++ trunk/core/src/classpath/javax/javax/print/attribute/standard/PrinterMoreInfo.java 2007-01-07 12:55:51 UTC (rev 3024) @@ -40,6 +40,7 @@ import java.... [truncated message content] |
From: <ls...@us...> - 2007-01-07 12:54:17
|
Revision: 3023 http://jnode.svn.sourceforge.net/jnode/?rev=3023&view=rev Author: lsantha Date: 2007-01-07 04:54:15 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/io/StreamTokenizer.java trunk/core/src/classpath/java/java/net/URI.java trunk/core/src/classpath/java/java/rmi/activation/ActivationID.java trunk/core/src/classpath/java/java/rmi/server/LoaderHandler.java trunk/core/src/classpath/java/java/rmi/server/RMIClassLoader.java trunk/core/src/classpath/java/java/rmi/server/RMIClassLoaderSpi.java trunk/core/src/classpath/java/java/rmi/server/UnicastRemoteObject.java trunk/core/src/classpath/java/java/security/AccessController.java trunk/core/src/classpath/java/java/security/MessageDigest.java trunk/core/src/classpath/java/java/security/MessageDigestSpi.java trunk/core/src/classpath/java/java/security/Signature.java trunk/core/src/classpath/java/java/security/SignatureSpi.java trunk/core/src/classpath/java/java/security/UnresolvedPermission.java trunk/core/src/classpath/java/java/security/acl/Acl.java trunk/core/src/classpath/java/java/security/acl/AclEntry.java trunk/core/src/classpath/java/java/security/acl/Group.java trunk/core/src/classpath/java/java/security/cert/CertPath.java trunk/core/src/classpath/java/java/security/cert/CertStore.java trunk/core/src/classpath/java/java/security/cert/CertStoreSpi.java trunk/core/src/classpath/java/java/security/cert/CertificateFactory.java trunk/core/src/classpath/java/java/security/cert/CertificateFactorySpi.java trunk/core/src/classpath/java/java/security/cert/CollectionCertStoreParameters.java trunk/core/src/classpath/java/java/security/cert/PKIXBuilderParameters.java trunk/core/src/classpath/java/java/security/cert/PKIXCertPathChecker.java trunk/core/src/classpath/java/java/security/cert/PKIXParameters.java trunk/core/src/classpath/java/java/security/cert/PolicyNode.java trunk/core/src/classpath/java/java/security/cert/PolicyQualifierInfo.java trunk/core/src/classpath/java/java/security/cert/X509CRL.java trunk/core/src/classpath/java/java/security/cert/X509CRLSelector.java trunk/core/src/classpath/java/java/security/cert/X509CertSelector.java trunk/core/src/classpath/java/java/security/cert/X509Certificate.java trunk/core/src/classpath/java/java/security/cert/X509Extension.java trunk/core/src/classpath/java/java/util/zip/Deflater.java Added Paths: ----------- trunk/core/src/classpath/java/java/awt/datatransfer/MimeType.java trunk/core/src/classpath/java/java/beans/ConstructorProperties.java trunk/core/src/classpath/java/java/math/RoundingMode.java trunk/core/src/classpath/java/java/net/Proxy.java trunk/core/src/classpath/java/java/net/ProxySelector.java trunk/core/src/classpath/java/java/net/ResolverCache.java Added: trunk/core/src/classpath/java/java/awt/datatransfer/MimeType.java =================================================================== --- trunk/core/src/classpath/java/java/awt/datatransfer/MimeType.java (rev 0) +++ trunk/core/src/classpath/java/java/awt/datatransfer/MimeType.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -0,0 +1,281 @@ +/* MimeType.java -- A helper class for mime handling in DataFlavor + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.StringTokenizer; + +/** + * A helper class for mime handling in DataFlavor. + * + * A Mauve test for DataFlavor.writeExternal() shows that a non-public + * class java.awt.datatransfer.MimeType gets serialized. This class + * is mainly here for serialization compatibility. Of course, + * now that we have it here, we can just as well implement some + * mime handling facility here. + */ +class MimeType + implements Externalizable +{ + + /** + * The primary type. + */ + private String primaryType; + + /** + * The subtype. + */ + private String subType; + + /** + * Additional parameters to be appended to the mime string. + */ + private HashMap parameters; + + /** + * This is only here for deserialization. + */ + public MimeType() + { + parameters = new HashMap(); + } + + /** + * Creates a new MimeType object. + * + * @param mime the mime type + */ + MimeType(String mime) + throws MimeTypeParseException + { + this(); + parse(mime); + } + + /** + * Adds a mime parameter. + * + * @param param the parameter key + * @param value the parameter value + */ + void addParameter(String param, String value) + { + parameters.put(param, value); + } + + /** + * Removes the parameter with the specified key. + * + * @param param the parameter to remove + */ + void removeParameter(String param) + { + parameters.remove(param); + } + + /** + * Returns the parameter for the <code>key</code>. + * + * @param key the parameter key + * + * @return the parameter for the <code>key</code> + */ + String getParameter(String key) + { + return (String) parameters.get(key); + } + + /** + * Returns the primary type. + * + * @return the primary type + */ + String getPrimaryType() + { + return primaryType; + } + + String getSubType() + { + return subType; + } + + /** + * Returns the base type of this mime type. This is the primary + * type plus the subtype, separated by '/'. + * + * @return the base type of this mime type + */ + String getBaseType() + { + return primaryType + '/' + subType; + } + + /** + * Returns <code>true</code> if this mime type and another mime type + * match. This will be true when their primary types are equal, and their + * subtypes are equal (or when either subtype is * ). + * + * @param other the other mime type + * + * @return <code>true</code> if the mime types match, <code>false</code> + * otherwise + */ + boolean matches(MimeType other) + { + boolean match = false; + if (other != null) + { + match = primaryType.equals(other.primaryType) + && (subType.equals("*") || other.subType.equals("*") + || subType.equals(other.subType)); + } + return match; + } + + /** + * Serializes the mime type. + * + * @param in the input stream to read from + * + * @throws ClassNotFoundException not thrown here + * @throws IOException when something goes wrong on the input stream, + * or when the mime type can't be parsed + */ + public void readExternal(ObjectInput in) + throws ClassNotFoundException, IOException + { + String mime = in.readUTF(); + parameters.clear(); + try + { + parse(mime); + } + catch (MimeTypeParseException ex) + { + IOException ioEx = new IOException(); + ioEx.initCause(ex); + throw ioEx; + } + } + + /** + * Serializes this mime type. + * + * @param out the output stream + * + * @throws IOException when something goes wrong on the output stream + */ + public void writeExternal(ObjectOutput out) + throws IOException + { + out.writeUTF(toString()); + } + + /** + * Creates a string representation of this mime type. + * + * @return a string representation of this mime type + */ + public String toString() + { + StringBuilder s = new StringBuilder(); + s.append(primaryType); + s.append('/'); + s.append(subType); + if (parameters.size() > 0) + { + Set entries = parameters.entrySet(); + for (Iterator i = entries.iterator(); i.hasNext();) + { + s.append("; "); + Map.Entry entry = (Map.Entry) i.next(); + s.append(entry.getKey()); + s.append('='); + s.append(entry.getValue()); + } + } + return s.toString(); + } + + /** + * Parses the specified mime type string and initializes the fields + * of this object. + * + * @param mime the mime type string + */ + private void parse(String mime) + throws MimeTypeParseException + { + // FIXME: Maybe implement more sophisticated mime string parsing according + // to RFC 2045 and 2046. + StringTokenizer tokenizer = new StringTokenizer(mime); + try + { + primaryType = tokenizer.nextToken("/"); + subType = tokenizer.nextToken("/;"); + } + catch (NoSuchElementException ex) + { + throw new MimeTypeParseException("Expected / separator"); + } + + // Add any parameters. + while (tokenizer.hasMoreTokens()) + { + String keyValuePair = tokenizer.nextToken(";"); + int i = keyValuePair.indexOf('='); + if (i == -1) + throw new MimeTypeParseException("Expected = as parameter separator"); + String key = keyValuePair.substring(0, i).trim(); + String value = keyValuePair.substring(i + 1).trim(); + parameters.put(key, value); + } + } + +} Added: trunk/core/src/classpath/java/java/beans/ConstructorProperties.java =================================================================== --- trunk/core/src/classpath/java/java/beans/ConstructorProperties.java (rev 0) +++ trunk/core/src/classpath/java/java/beans/ConstructorProperties.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -0,0 +1,72 @@ +/* ConstructorProperties.java - Associate constructor params with props + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.beans; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static java.lang.annotation.ElementType.CONSTRUCTOR; + +/** + * An annotation used to associate the parameters of a + * constructor with the accessor methods that later provide + * access to these values. For example, the parameters of + * the constructor <code>Person(String name, int age)</code> + * may be linked to the bean's two accessors, <code>getName()</code> + * and <code>getAge()</code> using + * <code>@ConstructorProperties({"name","age"})</code>. + * + * @author Andrew John Hughes (gnu...@me...) + * @since 1.6 + */ +@Documented @Retention(RUNTIME) @Target(CONSTRUCTOR) +public @interface ConstructorProperties +{ + + /** + * Contains the name of the accessor methods associated + * with each constructor parameter. + * + * @return the accessor method names corresponding to the + * constructor parameters. + */ + String[] value(); + +} Modified: trunk/core/src/classpath/java/java/io/StreamTokenizer.java =================================================================== --- trunk/core/src/classpath/java/java/io/StreamTokenizer.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/io/StreamTokenizer.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -330,6 +330,7 @@ { while ((ch = in.read()) != '\n' && ch != '\r' && ch != TT_EOF) ; + if (ch != TT_EOF) in.unread(ch); return nextToken(); // Recursive, but not too deep in normal cases @@ -431,6 +432,7 @@ { while ((ch = in.read()) != '\n' && ch != '\r' && ch != TT_EOF) ; + if (ch != TT_EOF) in.unread(ch); return nextToken(); // Recursive, but not too deep in normal cases. Added: trunk/core/src/classpath/java/java/math/RoundingMode.java =================================================================== --- trunk/core/src/classpath/java/java/math/RoundingMode.java (rev 0) +++ trunk/core/src/classpath/java/java/math/RoundingMode.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -0,0 +1,89 @@ +/* RoundingMode.java -- An Enum to replace BigDecimal rounding constants. + Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.math; + +/** + * An enum to specify rounding behaviour for numerical operations that may + * discard precision. + * @author Anthony Balkissoon abalkiss at redhat dot com + * + */ +public enum RoundingMode +{ + UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, UNNECESSARY; + + /** + * For compatability with Sun's JDK + */ + private static final long serialVersionUID = 432302042773881265L; + + /** + * Returns the RoundingMode object corresponding to the legacy rounding modes + * in BigDecimal. + * @param rm the legacy rounding mode + * @return the corresponding RoundingMode + */ + public static RoundingMode valueOf(int rm) + { + switch (rm) + { + case BigDecimal.ROUND_CEILING: + return CEILING; + case BigDecimal.ROUND_FLOOR: + return FLOOR; + case BigDecimal.ROUND_DOWN: + return DOWN; + case BigDecimal.ROUND_UP: + return UP; + case BigDecimal.ROUND_HALF_UP: + return HALF_UP; + case BigDecimal.ROUND_HALF_DOWN: + return HALF_DOWN; + case BigDecimal.ROUND_HALF_EVEN: + return HALF_EVEN; + case BigDecimal.ROUND_UNNECESSARY: + return UNNECESSARY; + default: + throw new + IllegalArgumentException("invalid argument: " + rm + + ". Argument should be one of the " + + "rounding modes defined in BigDecimal."); + } + } +} Added: trunk/core/src/classpath/java/java/net/Proxy.java =================================================================== --- trunk/core/src/classpath/java/java/net/Proxy.java (rev 0) +++ trunk/core/src/classpath/java/java/net/Proxy.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -0,0 +1,137 @@ +/* Proxy.java -- Represends a proxy for a network connection + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.net; + + +/** + * Defines a proxy setting. This setting contains a type (https, socks, + * direct) and a socket address. + * + * @since 1.5 + */ +public class Proxy +{ + /** + * Represents the proxy type. + */ + public enum Type + { + DIRECT, HTTP, SOCKS; + + /** + * For compatability with Sun's JDK + */ + private static final long serialVersionUID = -2231209257930100533L; + } + + public static final Proxy NO_PROXY = new Proxy(Type.DIRECT, null); + + private Type type; + private SocketAddress address; + + /** + * Creates a new <code>Proxy</code> object. + * + * @param type The type for this proxy + * @param address The address of this proxy + */ + public Proxy(Type type, SocketAddress address) + { + this.type = type; + this.address = address; + } + + /** + * Returns the socket address for this proxy object. + * + * @return the socket address + */ + public SocketAddress address() + { + return address; + } + + /** + * Returns the of this proxy instance. + * + * @return the type + * + * @see Type + */ + public Type type() + { + return type; + } + + /** + * Compares the given object with this object. + * + * @return <code>true</code> if both objects or equals, + * <code>false</code> otherwise. + */ + public final boolean equals(Object obj) + { + if (! (obj instanceof Proxy)) + return false; + + Proxy tmp = (Proxy) obj; + + return (type.equals(tmp.type) + && address.equals(tmp.address)); + } + + /** + * Returns the hashcode for this <code>Proxy</code> object. + * + * @return the hashcode + */ + public final int hashCode() + { + return type.hashCode() ^ address.hashCode(); + } + + /** + * Returns a string representation of this <code>Proxy</code> object. + * + * @return the string + */ + public String toString() + { + return type.toString() + ":" + address.toString(); + } +} Added: trunk/core/src/classpath/java/java/net/ProxySelector.java =================================================================== --- trunk/core/src/classpath/java/java/net/ProxySelector.java (rev 0) +++ trunk/core/src/classpath/java/java/net/ProxySelector.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -0,0 +1,117 @@ +/* ProxySelector.java -- A proxy selector class + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.net; + +import gnu.java.net.DefaultProxySelector; + +import java.io.IOException; +import java.util.List; + +/** + * Class for handling proxies for different connections. + * + * @since 1.5 + */ +public abstract class ProxySelector +{ + /** + * Default proxy selector. + */ + private static ProxySelector defaultSelector = new DefaultProxySelector(); + + /** + * Creates a new <code>ProxySelector</code> object. + */ + public ProxySelector() + { + // Do nothing here. + } + + /** + * Returns the default proxy selector. + * + * @return the default proxy selector + * + * @throws SecurityException If a security manager is installed and it + * denies NetPermission("getProxySelector") + */ + public static ProxySelector getDefault() + { + SecurityManager sm = System.getSecurityManager(); + + if (sm != null) + sm.checkPermission(new NetPermission("getProxySelector")); + + return defaultSelector; + } + + /** + * Sets the default proxy selector. + * + * @param selector the defualt proxy selector + * + * @throws SecurityException If a security manager is installed and it + * denies NetPermission("setProxySelector") + */ + public static void setDefault(ProxySelector selector) + { + SecurityManager sm = System.getSecurityManager(); + + if (sm != null) + sm.checkPermission(new NetPermission("setProxySelector")); + + defaultSelector = selector; + } + + /** + * Signals to the selector that a proxy was no available. + * + * @throws IllegalArgumentException If one argument is null + */ + public abstract void connectFailed(URI uri, SocketAddress address, + IOException exception); + + /** + * Returns the list of proxy settings for a given URI. + * + * @return list of proxy settings + * + * @throws IllegalArgumentException If uri is null + */ + public abstract List<Proxy> select(URI uri); +} Added: trunk/core/src/classpath/java/java/net/ResolverCache.java =================================================================== --- trunk/core/src/classpath/java/java/net/ResolverCache.java (rev 0) +++ trunk/core/src/classpath/java/java/net/ResolverCache.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -0,0 +1,269 @@ +/* ResolverCache.java -- A cache of resolver lookups for InetAddress. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.net; + +import java.security.Security; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; + +/** + * This class provides a cache of name service resolutions. By + * default successful resolutions are cached forever to guard + * against DNS spoofing attacks and failed resolutions are cached + * for 10 seconds to improve performance. The length of time that + * results remain in the cache is determined by the following + * security properties: + * <dl> + * <dt><code>networkaddress.cache.ttl</code></dt> + * <dd> + * This property specifies the length of time in seconds that + * successful resolutions remain in the cache. The default is + * -1, indicating to cache forever. + * </dd> + * <dt><code>networkaddress.cache.negative.ttl</code></dt> + * <dd> + * This property specifies the length of time in seconds that + * unsuccessful resolutions remain in the cache. The default + * is 10, indicating to cache for 10 seconds. + * </dd> + * In both cases, a value of -1 indicates to cache forever and a + * value of 0 indicates not to cache. + * + * @author Gary Benson (gb...@re...) + */ +class ResolverCache +{ + /** + * The time in seconds for which successful lookups are cached. + */ + private static final int POSITIVE_TTL = + getTTL("networkaddress.cache.ttl", -1); + + /** + * The time in seconds for which unsuccessful lookups are cached. + */ + private static final int NEGATIVE_TTL = + getTTL("networkaddress.cache.negative.ttl", 10); + + /** + * Helper function to set the TTLs. + */ + private static int getTTL(String propName, int defaultValue) + { + String propValue = Security.getProperty(propName); + if (propValue == null) + return defaultValue; + + return Integer.parseInt(propValue); + } + + /** + * The cache itself. + */ + private static HashMap<Object, Entry> cache = new HashMap<Object, Entry>(); + + /** + * List of entries which may expire. + */ + private static LinkedList<Entry> killqueue = new LinkedList<Entry>(); + + /** + * Return the hostname for the specified IP address. + * + * @param ip The IP address as a byte array + * + * @return The hostname + * + * @exception UnknownHostException If the reverse lookup fails + */ + public static String getHostByAddr(byte[] addr) throws UnknownHostException + { + Object key = makeHashableAddress(addr); + Entry entry = (Entry) get(key); + if (entry != null) + { + if (entry.value == null) + throw new UnknownHostException(); + return (String) entry.value; + } + + try + { + String hostname = VMInetAddress.getHostByAddr(addr); + put(new Entry(key, hostname)); + return hostname; + } + catch (UnknownHostException e) + { + put(new Entry(key, null)); + throw e; + } + } + + /** + * Return a list of all IP addresses for the specified hostname. + * + * @param hostname The hostname + * + * @return An list of IP addresses as byte arrays + * + * @exception UnknownHostException If the lookup fails + */ + public static byte[][] getHostByName(String hostname) + throws UnknownHostException + { + Entry entry = (Entry) get(hostname); + if (entry != null) + { + if (entry.value == null) + throw new UnknownHostException(); + return (byte[][]) entry.value; + } + + try + { + byte[][] addrs = VMInetAddress.getHostByName(hostname); + put(new Entry(hostname, addrs)); + return addrs; + } + catch (UnknownHostException e) + { + put(new Entry(hostname, null)); + throw e; + } + } + + /** + * Convert an IP address expressed as a byte array into something + * we can use as a hashtable key. + */ + private static Object makeHashableAddress(byte[] addr) + { + char[] chars = new char[addr.length]; + for (int i = 0; i < addr.length; i++) + chars[i] = (char) addr[i]; + return new String(chars); + } + + /** + * Return the entry in the cache associated with the supplied key, + * or <code>null</code> if the cache does not contain an entry + * associated with this key. + */ + private static synchronized Entry get(Object key) + { + reap(); + return (Entry) cache.get(key); + } + + /** + * Insert the supplied entry into the cache. + */ + private static synchronized void put(Entry entry) + { + reap(); + if (entry.expires != 0) + { + if (entry.expires != -1) + killqueue.add(entry); + cache.put(entry.key, entry); + } + } + + /** + * Clear expired entries. This method is not synchronized, so + * it must only be called by methods that are. + */ + private static void reap() + { + if (!killqueue.isEmpty()) + { + long now = System.currentTimeMillis(); + + Iterator iter = killqueue.iterator(); + while (iter.hasNext()) + { + Entry entry = (Entry) iter.next(); + if (entry.expires > now) + break; + cache.remove(entry.key); + iter.remove(); + } + } + } + + /** + * An entry in the cache. + */ + private static class Entry + { + /** + * The key by which this entry is referenced. + */ + public final Object key; + + /** + * The entry itself. A null value indicates a failed lookup. + */ + public final Object value; + + /** + * The time when this cache entry expires. If set to -1 then + * this entry will never expire. If set to 0 then this entry + * expires immediately and will not be inserted into the cache. + */ + public final long expires; + + /** + * Constructor. + */ + public Entry(Object key, Object value) + { + this.key = key; + this.value = value; + + int ttl = value != null ? POSITIVE_TTL : NEGATIVE_TTL; + if (ttl < 1) + expires = ttl; + else + expires = System.currentTimeMillis() + ttl * 1000; + } + } +} Modified: trunk/core/src/classpath/java/java/net/URI.java =================================================================== --- trunk/core/src/classpath/java/java/net/URI.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/net/URI.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -156,7 +156,7 @@ * @since 1.4 */ public final class URI - implements Comparable, Serializable + implements Comparable<URI>, Serializable { /** * For serialization compatability. @@ -1229,7 +1229,7 @@ } /** - * Compare the URI with another object that must also be a URI. + * Compare the URI with another URI. * Undefined components are taken to be less than any other component. * The following criteria are observed: * </p> @@ -1265,16 +1265,14 @@ * </ul> * </ul> * - * @param obj This object to compare this URI with + * @param uri The other URI to compare this URI with * @return a negative integer, zero or a positive integer depending * on whether this URI is less than, equal to or greater * than that supplied, respectively. - * @throws ClassCastException if the given object is not a URI */ - public int compareTo(Object obj) + public int compareTo(URI uri) throws ClassCastException { - URI uri = (URI) obj; if (scheme == null && uri.getScheme() != null) return -1; if (scheme != null) Modified: trunk/core/src/classpath/java/java/rmi/activation/ActivationID.java =================================================================== --- trunk/core/src/classpath/java/java/rmi/activation/ActivationID.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/rmi/activation/ActivationID.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -174,7 +174,7 @@ { out.writeObject(uid); out.writeObject(activator); - }; + } /** * Compare by .equals if both a and b are not null, compare directly if at Modified: trunk/core/src/classpath/java/java/rmi/server/LoaderHandler.java =================================================================== --- trunk/core/src/classpath/java/java/rmi/server/LoaderHandler.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/rmi/server/LoaderHandler.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -42,6 +42,7 @@ /** * @deprecated + * @since 1.1 */ public interface LoaderHandler { @@ -54,13 +55,13 @@ /** * @deprecated */ - Class loadClass(String name) + Class<?> loadClass(String name) throws MalformedURLException, ClassNotFoundException; /** * @deprecated */ - Class loadClass(URL codebase, String name) + Class<?> loadClass(URL codebase, String name) throws MalformedURLException, ClassNotFoundException; /** Modified: trunk/core/src/classpath/java/java/rmi/server/RMIClassLoader.java =================================================================== --- trunk/core/src/classpath/java/java/rmi/server/RMIClassLoader.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/rmi/server/RMIClassLoader.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -51,6 +51,7 @@ * network-based class loading in RMI. These methods are called by RMI's * internal marshal streams to implement the dynamic class loading of types for * RMI parameters and return values. + * @since 1.1 */ public class RMIClassLoader { @@ -62,13 +63,13 @@ /** * @deprecated */ - public static Class loadClass(String name) + public static Class<?> loadClass(String name) throws MalformedURLException, ClassNotFoundException { return loadClass("", name); } - public static Class loadClass(String codebase, String name) + public static Class<?> loadClass(String codebase, String name) throws MalformedURLException, ClassNotFoundException { RMIClassLoaderSpi spi = getProviderInstance(); @@ -77,7 +78,7 @@ return spi.loadClass(codebase, name, null); } - public static Class loadClass(String codebase, String name, + public static Class<?> loadClass(String codebase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException { @@ -87,7 +88,7 @@ return spi.loadClass(codebase, name, defaultLoader); } - public static Class loadProxyClass (String codeBase, String[] interfaces, + public static Class<?> loadProxyClass (String codeBase, String[] interfaces, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException { @@ -114,7 +115,7 @@ * @throws MalformedURLException if the URL is not well formed * @throws ClassNotFoundException if the requested class cannot be found */ - public static Class loadClass(URL codeBase, String name) + public static Class<?> loadClass(URL codeBase, String name) throws MalformedURLException, ClassNotFoundException { RMIClassLoaderSpi spi = getProviderInstance(); @@ -151,7 +152,7 @@ * @return a space seperated list of URLs where the class-definition * of cl may be found */ - public static String getClassAnnotation(Class cl) + public static String getClassAnnotation(Class<?> cl) { RMIClassLoaderSpi spi = getProviderInstance(); if (spi == null) Modified: trunk/core/src/classpath/java/java/rmi/server/RMIClassLoaderSpi.java =================================================================== --- trunk/core/src/classpath/java/java/rmi/server/RMIClassLoaderSpi.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/rmi/server/RMIClassLoaderSpi.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -49,16 +49,16 @@ { } - public abstract Class loadClass (String codeBase, String name, + public abstract Class<?> loadClass (String codeBase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException; - public abstract Class loadProxyClass (String codeBase, String[] interfaces, + public abstract Class<?> loadProxyClass (String codeBase, String[] interfaces, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException; public abstract ClassLoader getClassLoader (String codebase) throws MalformedURLException; - public abstract String getClassAnnotation (Class cl); + public abstract String getClassAnnotation (Class<?> cl); } Modified: trunk/core/src/classpath/java/java/rmi/server/UnicastRemoteObject.java =================================================================== --- trunk/core/src/classpath/java/java/rmi/server/UnicastRemoteObject.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/rmi/server/UnicastRemoteObject.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -239,11 +239,12 @@ (UnicastServerRef) ((RemoteObject) obj).getRef(); return sref.unexportObject(obj, force); } - else + // FIXME + /* else { - // FIXME ; } + */ return true; } Modified: trunk/core/src/classpath/java/java/security/AccessController.java =================================================================== --- trunk/core/src/classpath/java/java/security/AccessController.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/security/AccessController.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -91,12 +91,12 @@ * should be be called. * @return the result of the <code>action.run()</code> method. */ - public static Object doPrivileged(PrivilegedAction action) + public static <T> T doPrivileged(PrivilegedAction<T> action) { if (action == null) { Unsafe.debug("action == null!! "); } - return VmAccessController.doPrivileged(action, null); + return (T) VmAccessController.doPrivileged(action, null); } /** @@ -135,10 +135,10 @@ * @exception PrivilegedActionException wrapped around any exception that * is thrown in the <code>run()</code> method. */ - public static Object doPrivileged(PrivilegedExceptionAction action) + public static <T> T doPrivileged(PrivilegedExceptionAction<T> action) throws PrivilegedActionException { - return VmAccessController.doPrivileged(action, null); + return (T) VmAccessController.doPrivileged(action, null); } /** Modified: trunk/core/src/classpath/java/java/security/MessageDigest.java =================================================================== --- trunk/core/src/classpath/java/java/security/MessageDigest.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/security/MessageDigest.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -38,7 +38,10 @@ package java.security; import gnu.java.security.Engine; +import java.nio.ByteBuffer; +import java.lang.reflect.InvocationTargetException; + /** * Message digests are secure one-way hash functions that take arbitrary-sized * data and output a fixed-length hash value. @@ -72,28 +75,29 @@ * Returns a new instance of <code>MessageDigest</code> representing the * specified algorithm. * - * @param algorithm - * the name of the digest algorithm to use. + * @param algorithm the name of the digest algorithm to use. * @return a new instance representing the desired algorithm. - * @throws NoSuchAlgorithmException - * if the algorithm is not implemented by any provider. + * @throws NoSuchAlgorithmException if the algorithm is not implemented by any + * provider. + * @throws IllegalArgumentException if <code>algorithm</code> is + * <code>null</code> or is an empty string. */ public static MessageDigest getInstance(String algorithm) throws NoSuchAlgorithmException { Provider[] p = Security.getProviders(); + NoSuchAlgorithmException lastException = null; for (int i = 0; i < p.length; i++) - { try { return getInstance(algorithm, p[i]); } - catch (NoSuchAlgorithmException ignored) + catch (NoSuchAlgorithmException x) { - // Ignore. + lastException = x; } - } - + if (lastException != null) + throw lastException; throw new NoSuchAlgorithmException(algorithm); } @@ -101,29 +105,26 @@ * Returns a new instance of <code>MessageDigest</code> representing the * specified algorithm from a named provider. * - * @param algorithm - * the name of the digest algorithm to use. - * @param provider - * the name of the provider to use. + * @param algorithm the name of the digest algorithm to use. + * @param provider the name of the provider to use. * @return a new instance representing the desired algorithm. - * @throws NoSuchAlgorithmException - * if the algorithm is not implemented by the named provider. - * @throws NoSuchProviderException - * if the named provider was not found. + * @throws NoSuchAlgorithmException if the algorithm is not implemented by the + * named provider. + * @throws NoSuchProviderException if the named provider was not found. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code> or empty. */ public static MessageDigest getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { - if (provider != null) + if (provider == null) + throw new IllegalArgumentException("provider MUST NOT be null"); provider = provider.trim(); - - if (provider == null || provider.length() == 0) - throw new IllegalArgumentException("Illegal provider"); - + if (provider.length() == 0) + throw new IllegalArgumentException("provider MUST NOT be empty"); Provider p = Security.getProvider(provider); if (p == null) throw new NoSuchProviderException(provider); - return getInstance(algorithm, p); } @@ -131,39 +132,43 @@ * Returns a new instance of <code>MessageDigest</code> representing the * specified algorithm from a designated {@link Provider}. * - * @param algorithm - * the name of the digest algorithm to use. - * @param provider - * the {@link Provider} to use. + * @param algorithm the name of the digest algorithm to use. + * @param provider the {@link Provider} to use. * @return a new instance representing the desired algorithm. - * @throws IllegalArgumentException - * if <code>provider</code> is <code>null</code>. - * @throws NoSuchAlgorithmException - * if the algorithm is not implemented by {@link Provider}. + * @throws NoSuchAlgorithmException if the algorithm is not implemented by + * {@link Provider}. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>algorithm</code> is an empty string. * @since 1.4 * @see Provider */ public static MessageDigest getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { - if (provider == null) - throw new IllegalArgumentException("Illegal provider"); - - MessageDigest result = null; - Object o = null; + StringBuilder sb = new StringBuilder("MessageDigest for algorithm [") + .append(algorithm).append("] from provider[") + .append(provider).append("] "); + Object o; try { o = Engine.getInstance(MESSAGE_DIGEST, algorithm, provider); } - catch (java.lang.reflect.InvocationTargetException ite) + catch (InvocationTargetException x) { - throw new NoSuchAlgorithmException(algorithm); + Throwable cause = x.getCause(); + if (cause instanceof NoSuchAlgorithmException) + throw (NoSuchAlgorithmException) cause; + if (cause == null) + cause = x; + sb.append("could not be created"); + NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString()); + y.initCause(cause); + throw y; } - + MessageDigest result; if (o instanceof MessageDigestSpi) - { result = new DummyMessageDigest((MessageDigestSpi) o, algorithm); - } else if (o instanceof MessageDigest) { result = (MessageDigest) o; @@ -171,7 +176,8 @@ } else { - throw new NoSuchAlgorithmException(algorithm); + sb.append("is of an unexpected Type: ").append(o.getClass().getName()); + throw new NoSuchAlgorithmException(sb.toString()); } result.provider = provider; return result; @@ -224,6 +230,17 @@ } /** + * Updates the digest with the remaining bytes of a buffer. + * + * @param input The input byte buffer. + * @since 1.5 + */ + public void update (ByteBuffer input) + { + engineUpdate (input); + } + + /** * Computes the final digest of the stored data. * * @return a byte array representing the message digest. Modified: trunk/core/src/classpath/java/java/security/MessageDigestSpi.java =================================================================== --- trunk/core/src/classpath/java/java/security/MessageDigestSpi.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/security/MessageDigestSpi.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -37,6 +37,8 @@ package java.security; +import java.nio.ByteBuffer; + /** This is the Service Provider Interface (SPI) for MessageDigest class in java.security. It provides the back end functionality @@ -98,6 +100,23 @@ protected abstract void engineUpdate(byte[]input, int offset, int len); /** + * Updates this digest with the remaining bytes of a byte buffer. + * + * @param input The input buffer. + * @since 1.5 + */ + protected void engineUpdate (ByteBuffer input) + { + byte[] buf = new byte[1024]; + while (input.hasRemaining()) + { + int n = Math.min(input.remaining(), buf.length); + input.get (buf, 0, n); + engineUpdate (buf, 0, n); + } + } + + /** Computes the final digest of the stored bytes and returns them. It performs any necessary padding. The message digest should reset sensitive data after performing the digest. Modified: trunk/core/src/classpath/java/java/security/Signature.java =================================================================== --- trunk/core/src/classpath/java/java/security/Signature.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/security/Signature.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -40,6 +40,8 @@ import gnu.java.security.Engine; +import java.lang.reflect.InvocationTargetException; +import java.nio.ByteBuffer; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.security.spec.AlgorithmParameterSpec; @@ -127,28 +129,29 @@ * Returns an instance of <code>Signature</code> representing the specified * signature. * - * @param algorithm - * the algorithm to use. + * @param algorithm the algorithm to use. * @return a new instance repesenting the desired algorithm. - * @throws NoSuchAlgorithmException - * if the algorithm is not implemented by any provider. + * @throws NoSuchAlgorithmException if the algorithm is not implemented by any + * provider. + * @throws IllegalArgumentException if <code>algorithm</code> is + * <code>null</code> or is an empty string. */ public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException { Provider[] p = Security.getProviders(); + NoSuchAlgorithmException lastException = null; for (int i = 0; i < p.length; i++) - { try { return getInstance(algorithm, p[i]); } - catch (NoSuchAlgorithmException e) + catch (NoSuchAlgorithmException x) { - // Ignored. + lastException = x; } - } - + if (lastException != null) + throw lastException; throw new NoSuchAlgorithmException(algorithm); } @@ -156,28 +159,26 @@ * Returns an instance of <code>Signature</code> representing the specified * signature from the named provider. * - * @param algorithm - * the algorithm to use. - * @param provider - * the name of the provider to use. + * @param algorithm the algorithm to use. + * @param provider the name of the provider to use. * @return a new instance repesenting the desired algorithm. - * @throws IllegalArgumentException if <code>provider</code> is - * <code>null</code> or is an empty string. - * @throws NoSuchProviderException - * if the named provider was not found. - * @throws NoSuchAlgorithmException - * if the algorithm is not implemented by the named provider. + * @throws NoSuchProviderException if the named provider was not found. + * @throws NoSuchAlgorithmException if the algorithm is not implemented by the + * named provider. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code> or empty. */ public static Signature getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { - if (provider == null || provider.length() == 0) - throw new IllegalArgumentException("Illegal provider"); - + if (provider == null) + throw new IllegalArgumentException("provider MUST NOT be null"); + provider = provider.trim(); + if (provider.length() == 0) + throw new IllegalArgumentException("provider MUST NOT be empty"); Provider p = Security.getProvider(provider); if (p == null) throw new NoSuchProviderException(provider); - return getInstance(algorithm, p); } @@ -185,35 +186,41 @@ * Returns an instance of <code>Signature</code> representing the specified * signature from the specified {@link Provider}. * - * @param algorithm - * the algorithm to use. - * @param provider - * the {@link Provider} to use. + * @param algorithm the algorithm to use. + * @param provider the {@link Provider} to use. * @return a new instance repesenting the desired algorithm. - * @throws NoSuchAlgorithmException - * if the algorithm is not implemented by the {@link Provider}. + * @throws NoSuchAlgorithmException if the algorithm is not implemented by the + * {@link Provider}. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>algorithm</code> is an empty string. */ public static Signature getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { - if (provider == null) - throw new IllegalArgumentException("Illegal provider"); - - Signature result = null; - Object o = null; + StringBuilder sb = new StringBuilder("Signature algorithm [") + .append(algorithm).append("] from provider[") + .append(provider).append("] "); + Object o; try { o = Engine.getInstance(SIGNATURE, algorithm, provider); } - catch (java.lang.reflect.InvocationTargetException ite) + catch (InvocationTargetException x) { - throw new NoSuchAlgorithmException(algorithm); + Throwable cause = x.getCause(); + if (cause instanceof NoSuchAlgorithmException) + throw (NoSuchAlgorithmException) cause; + if (cause == null) + cause = x; + sb.append("could not be created"); + NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString()); + y.initCause(cause); + throw y; } - + Signature result; if (o instanceof SignatureSpi) - { result = new DummySignature((SignatureSpi) o, algorithm); - } else if (o instanceof Signature) { result = (Signature) o; @@ -221,7 +228,8 @@ } else { - throw new NoSuchAlgorithmException(algorithm); + sb.append("is of an unexpected Type: ").append(o.getClass().getName()); + throw new NoSuchAlgorithmException(sb.toString()); } result.provider = provider; return result; @@ -469,6 +477,22 @@ } /** + * Update this signature with the {@link java.nio.Buffer#remaining()} + * bytes of the input buffer. + * + * @param input The input buffer. + * @throws SignatureException If this instance was not properly + * initialized. + */ + public final void update(ByteBuffer input) throws SignatureException + { + if (state != UNINITIALIZED) + engineUpdate(input); + else + throw new SignatureException("not initialized"); + } + + /** * Returns the name of the algorithm currently used. The names of algorithms * are usually SHA/DSA or SHA/RSA. * Modified: trunk/core/src/classpath/java/java/security/SignatureSpi.java =================================================================== --- trunk/core/src/classpath/java/java/security/SignatureSpi.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/security/SignatureSpi.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -37,6 +37,7 @@ package java.security; +import java.nio.ByteBuffer; import java.security.spec.AlgorithmParameterSpec; /** @@ -131,6 +132,24 @@ throws SignatureException; /** + * Update this signature with the {@link java.nio.Buffer#remaining()} + * bytes of the given buffer. + * + * @param input The input buffer. + * @throws SignatureException + */ + protected void engineUpdate(ByteBuffer input) throws SignatureException + { + byte[] buf = new byte[4096]; + while (input.hasRemaining()) + { + int l = Math.min(input.remaining(), buf.length); + input.get(buf, 0, l); + engineUpdate(buf, 0, l); + } + } + + /** * Returns the signature bytes of all the data fed to this instance. The * format of the output depends on the underlying signature algorithm. * Modified: trunk/core/src/classpath/java/java/security/UnresolvedPermission.java =================================================================== --- trunk/core/src/classpath/java/java/security/UnresolvedPermission.java 2007-01-07 12:53:02 UTC (rev 3022) +++ trunk/core/src/classpath/java/java/security/UnresolvedPermission.java 2007-01-07 12:54:15 UTC (rev 3023) @@ -201,6 +201,47 @@ { return new UnresolvedPermissionCollection(); } + + /** + * Return the name of the class of the unresolved permission. + * @since 1.5 + */ + public String getUnresolvedType() + { + return type; + } + + /** + * Return the name of the unresolved permission. + * @since 1.5 + */ + public String getUnresolvedName() + { + return name; + } + + /** + * Return the actions of the unresolved permission, or null + * if there are no actions. + * @since 1.5 + */ + public String getUnresolvedActions() + { + return actions; + } + + /** + * Return the certificates of the unresolved permission. + * If there are no certificates, null is returned. Otherwise, + * a new array is returned. + * @since 1.5 + */ + public Certificate[] getUnresolvedCerts() + { + if (certs == null) + return null; + return (Certificate[]) certs.clone(); + } } // class UnresolvedPermission /** Modified: trunk/core/src/class... [truncated message content] |
From: <ls...@us...> - 2007-01-07 12:53:05
|
Revision: 3022 http://jnode.svn.sourceforge.net/jnode/?rev=3022&view=rev Author: lsantha Date: 2007-01-07 04:53:02 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/lang/Character.java trunk/core/src/classpath/java/java/lang/Enum.java trunk/core/src/classpath/java/java/lang/System.java trunk/core/src/classpath/java/java/lang/management/ManagementFactory.java trunk/core/src/classpath/java/java/lang/management/MemoryPoolMXBean.java trunk/core/src/classpath/java/java/lang/management/MemoryUsage.java trunk/core/src/classpath/java/java/lang/management/OperatingSystemMXBean.java trunk/core/src/classpath/java/java/lang/management/RuntimeMXBean.java trunk/core/src/classpath/java/java/lang/management/ThreadInfo.java trunk/core/src/classpath/java/java/lang/management/ThreadMXBean.java Added Paths: ----------- trunk/core/src/classpath/java/java/lang/ProcessBuilder.java trunk/core/src/classpath/java/java/lang/management/LockInfo.java trunk/core/src/classpath/java/java/lang/management/MemoryType.java trunk/core/src/classpath/java/java/lang/management/MonitorInfo.java Modified: trunk/core/src/classpath/java/java/lang/Character.java =================================================================== --- trunk/core/src/classpath/java/java/lang/Character.java 2007-01-07 12:51:25 UTC (rev 3021) +++ trunk/core/src/classpath/java/java/lang/Character.java 2007-01-07 12:53:02 UTC (rev 3022) @@ -156,7 +156,7 @@ private final String canonicalName; /** Enumeration for the <code>forName()</code> method */ - private enum NameType { CANONICAL, NO_SPACES, CONSTANT; }; + private enum NameType { CANONICAL, NO_SPACES, CONSTANT; } /** * Constructor for strictly defined blocks. Modified: trunk/core/src/classpath/java/java/lang/Enum.java =================================================================== --- trunk/core/src/classpath/java/java/lang/Enum.java 2007-01-07 12:51:25 UTC (rev 3021) +++ trunk/core/src/classpath/java/java/lang/Enum.java 2007-01-07 12:53:02 UTC (rev 3022) @@ -60,13 +60,13 @@ /** * The name of this enum constant. */ - String name; + final String name; /** * The number of this enum constant. Each constant is given a number * which matches the order in which it was declared, starting with zero. */ - int ordinal; + final int ordinal; /** * This constructor is used by the compiler to create enumeration constants. @@ -220,4 +220,14 @@ k = k.getSuperclass(); return k; } + + /** + * Enumerations can not have finalization methods. + * + * @since 1.6 + */ + protected final void finalize() + { + } + } Added: trunk/core/src/classpath/java/java/lang/ProcessBuilder.java =================================================================== --- trunk/core/src/classpath/java/java/lang/ProcessBuilder.java (rev 0) +++ trunk/core/src/classpath/java/java/lang/ProcessBuilder.java 2007-01-07 12:53:02 UTC (rev 3022) @@ -0,0 +1,337 @@ +/* ProcessBuilder.java - Represent spawned system process + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import java.io.File; +import java.io.IOException; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * <p> + * This class is used to construct new operating system processes. + * A <code>ProcessBuilder</code> instance basically represent a + * template for a new process. Actual processes are generated from + * this template via use of the <code>start()</code> method, which + * may be invoked multiple times, with each invocation spawning a + * new process with the current attributes of the + * <code>ProcessBuilder</code> object. Each spawned process is + * independent of the <code>ProcessBuilder</code> object, and is + * unaffected by changes in its attributes. + * </p> + * <p> + * The following attributes define a process: + * </p> + * <ul> + * <li>The <emphasis>working directory</emphasis>; the activities of a + * process begin with the current directory set to this. By default, + * this is the working directory of the current process, as defined + * by the <code>user.dir</code> property.</li> + * <li>The <emphasis>command</emphasis> which invokes the process. This + * usually consists of the name of the program binary followed by an + * arbitrary number of arguments. For example, <code>find -type f</code> + * invokes the <code>find</code> binary with the arguments "-type" and "f". + * The command is provided a list, the elements of which are defined in a + * system dependent manner; the layout is affected by expected operating + * system conventions. A common method is to split the command on each + * space within the string. Thus, <code>find -type f</code> forms a + * three element list. However, in some cases, the expectation is that + * this split is performed by the program itself; thus, the list consists + * of only two elements (the program name and its arguments).</li> + * <li>The <emphasis>environment map</emphasis>, which links environment + * variables to their corresponding values. The initial contents of the map + * are the current environment values i.e. it contains the contents of the + * map returned by <code>System.getenv()</code>.</li> + * <li>The <emphasis>redirection flag</emphasis>, which specifies whether + * or not the contents of the error stream should be redirected to standard + * output. By default, this is false, and there are two output streams, one + * for normal data ({@link Process#getOutputStream()}) and one for error data + * ({@link Process#getErrorStream()}). When set to true, the two are merged, + * which simplifies the interleaving of the two streams. Data is read using + * the stream returned by {@link Process#getOutputStream()}, and the + * stream returned by {@link Process#getErrorStream()} throws an immediate + * end-of-file exception.</li> + * </ul> + * <p> + * All checks on attribute validity are delayed until <code>start()</code> + * is called. <code>ProcessBuilder</code> objects are <strong>not + * synchronized</strong>; the user must provide external synchronization + * where multiple threads may interact with the same + * <code>ProcessBuilder</code> object. + * </p> + * + * @author Tom Tromey (tr...@re...) + * @author Andrew John Hughes (gnu...@me...) + * @see Process + * @see System#getenv() + * @since 1.5 + */ +public final class ProcessBuilder +{ + + /** + * The working directory of the process. + */ + private File directory = new File(System.getProperty("user.dir")); + + /** + * The command line syntax for invoking the process. + */ + private List<String> command; + + /** + * The mapping of environment variables to values. + */ + private Map<String, String> environment = + new System.EnvironmentMap(System.getenv()); + + /** + * A flag indicating whether to redirect the error stream to standard + * output. + */ + private boolean redirect = false; + + /** + * Constructs a new <code>ProcessBuilder</code> with the specified + * command being used to invoke the process. The list is used directly; + * external changes are reflected in the <code>ProcessBuilder</code>. + * + * @param command the name of the program followed by its arguments. + */ + public ProcessBuilder(List<String> command) + { + this.command = command; + } + + /** + * Constructs a new <code>ProcessBuilder</code> with the specified + * command being used to invoke the process. This constructor + * simplifies creating a new <code>ProcessBuilder</code> by + * converting the provided series of constructor arguments into a + * list of command-line arguments. + * + * @param command the name of the program followed by its arguments. + */ + public ProcessBuilder(String... command) + { + this.command = Arrays.asList(command); + } + + /** + * Returns the current command line, used to invoke the process. + * The return value is simply a reference to the list of command + * line arguments used by the <code>ProcessBuilder</code> object; + * any changes made to it will be reflected in the operation of + * the <code>ProcessBuilder</code>. + * + * @return the list of command-line arguments. + */ + public List<String> command() + { + return command; + } + + /** + * Sets the command-line arguments to those specified. The list is + * used directly; external changes are reflected in the + * <code>ProcessBuilder</code>. + * + * @param command the name of the program followed by its arguments. + * @return a reference to this process builder. + */ + public ProcessBuilder command(List<String> command) + { + this.command = command; + return this; + } + + /** + * Sets the command-line arguments to those specified. + * This simplifies modifying the arguments by converting + * the provided series of constructor arguments into a + * list of command-line arguments. + * + * @param command the name of the program followed by its arguments. + * @return a reference to this process builder. + */ + public ProcessBuilder command(String... command) + { + this.command = Arrays.asList(command); + return this; + } + + /** + * Returns the working directory of the process. The + * returned value may be <code>null</code>; this + * indicates that the default behaviour of using the + * working directory of the current process should + * be adopted. + * + * @return the working directory. + */ + public File directory() + { + return directory; + } + + /** + * Sets the working directory to that specified. + * The supplied argument may be <code>null</code>, + * which indicates the default value should be used. + * The default is the working directory of the current + * process. + * + * @param directory the new working directory. + * @return a reference to this process builder. + */ + public ProcessBuilder directory(File directory) + { + this.directory = directory; + return this; + } + + /** + * <p> + * Returns the system environment variables of the process. + * If the underlying system does not support environment variables, + * an empty map is returned. + * </p> + * <p> + * The returned map does not accept queries using + * null keys or values, or those of a type other than + * <code>String</code>. Attempts to pass in a null value will + * throw a <code>NullPointerException</code>. Types other than + * <code>String</code> throw a <code>ClassCastException</code>. + * </p> + * <p> + * As the returned map is generated using data from the underlying + * platform, it may not comply with the <code>equals()</code> + * and <code>hashCode()</code> contracts. It is also likely that + * the keys of this map will be case-sensitive. + * </p> + * <p> + * Modification of the map is reliant on the underlying platform; + * some may not allow any changes to the environment variables or + * may prevent certain values being used. Attempts to do so will + * throw an <code>UnsupportedOperationException</code> or + * <code>IllegalArgumentException</code>, respectively. + * </p> + * <p> + * Use of this method may require a security check for the + * RuntimePermission "getenv.*". + * </p> + * + * @return a map of the system environment variables for the process. + * @throws SecurityException if the checkPermission method of + * an installed security manager prevents access to + * the system environment variables. + * @since 1.5 + */ + public Map<String, String> environment() + { + return environment; + } + + /** + * Returns true if the output stream and error stream of the + * process will be merged to form one composite stream. The + * default return value is <code>false</code>. + * + * @return true if the output stream and error stream are to + * be merged. + */ + public boolean redirectErrorStream() + { + return redirect; + } + + /** + * Sets the error stream redirection flag. If set, the output + * and error streams are merged to form one composite stream. + * + * @param redirect the new value of the redirection flag. + * @return a reference to this process builder. + */ + public ProcessBuilder redirectErrorStream(boolean redirect) + { + this.redirect = redirect; + return this; + } + + /** + * <p> + * Starts execution of a new process, based on the attributes of + * this <code>ProcessBuilder</code> object. This is the point + * at which the command-line arguments are checked. The list + * must be non-empty and contain only non-null string objects. + * The other attributes have default values which are used in + * cases where their values are not explicitly specified. + * </p> + * <p> + * If a security manager is in place, then the + * {@link SecurityManager#checkExec()} method is called to + * ensure that permission is given to execute the process. + * </p> + * <p> + * The execution of the process is system-dependent. Various + * exceptions may result, due to problems at the operating system + * level. These are all returned as a form of {@link IOException}. + * </p> + * + * @return a <code>Process</code> object, representing the spawned + * subprocess. + * @throws IOException if a problem occurs with executing the process + * at the operating system level. + * @throws IndexOutOfBoundsException if the command to execute is + * actually an empty list. + * @throws NullPointerException if the command to execute is null + * or the list contains null elements. + * @throws SecurityException if a security manager exists and prevents + * execution of the subprocess. + */ + public Process start() throws IOException + { + SecurityManager sm = SecurityManager.current; // Be thread-safe! + if (sm != null) + sm.checkExec(command.get(0)); + return VMProcess.exec(command, environment, directory, redirect); + } +} Modified: trunk/core/src/classpath/java/java/lang/System.java =================================================================== --- trunk/core/src/classpath/java/java/lang/System.java 2007-01-07 12:51:25 UTC (rev 3021) +++ trunk/core/src/classpath/java/java/lang/System.java 2007-01-07 12:53:02 UTC (rev 3022) @@ -149,7 +149,6 @@ SecurityManager sm = SecurityManager.current; // Be thread-safe. if (sm != null) sm.checkPermission(new RuntimePermission("setIO")); - VMSystem.setOut(out); } @@ -263,9 +262,7 @@ */ public static long nanoTime() { - //todo - throw new RuntimeException("Implement it"); - //return VMSystem.nanoTime(); + return VMSystem.nanoTime(); } /** @@ -464,6 +461,29 @@ } /** + * Remove a single system property by name. A security check may be + * performed, <code>checkPropertyAccess(key, "write")</code>. + * + * @param key the name of the system property to remove + * @return the previous value, or null + * @throws SecurityException if permission is denied + * @throws NullPointerException if key is null + * @throws IllegalArgumentException if key is "" + * @since 1.5 + */ + public static String clearProperty(String key) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPermission(new PropertyPermission(key, "write")); + // This handles both the null pointer exception and the illegal + // argument exception. + if (key.length() == 0) + throw new IllegalArgumentException("key can't be empty"); + return SystemProperties.remove(key); + } + + /** * Gets the value of an environment variable. * * @param name the name of the environment variable @@ -486,6 +506,60 @@ } /** + * <p> + * Returns an unmodifiable view of the system environment variables. + * If the underlying system does not support environment variables, + * an empty map is returned. + * </p> + * <p> + * The returned map is read-only and does not accept queries using + * null keys or values, or those of a type other than <code>String</code>. + * Attempts to modify the map will throw an + * <code>UnsupportedOperationException</code>, while attempts + * to pass in a null value will throw a + * <code>NullPointerException</code>. Types other than <code>String</code> + * throw a <code>ClassCastException</code>. + * </p> + * <p> + * As the returned map is generated using data from the underlying + * platform, it may not comply with the <code>equals()</code> + * and <code>hashCode()</code> contracts. It is also likely that + * the keys of this map will be case-sensitive. + * </p> + * <p> + * Use of this method may require a security check for the + * RuntimePermission "getenv.*". + * </p> + * + * @return a map of the system environment variables. + * @throws SecurityException if the checkPermission method of + * an installed security manager prevents access to + * the system environment variables. + * @since 1.5 + */ + public static Map<String, String> getenv() + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPermission(new RuntimePermission("getenv.*")); + if (environmentMap == null) + { + List<String> environ = (List<String>)VMSystem.environ(); + Map<String,String> variables = new EnvironmentMap(); + for (String pair : environ) + { + String[] parts = pair.split("="); + if (parts.length == 2) + variables.put(parts[0], parts[1]); + else + variables.put(parts[0], ""); + } + environmentMap = Collections.unmodifiableMap(variables); + } + return environmentMap; + } + + /** * Terminate the Virtual Machine. This just calls * <code>Runtime.getRuntime().exit(status)</code>, and never returns. * Obviously, a security check is in order, <code>checkExit</code>. @@ -597,4 +671,419 @@ return VMRuntime.mapLibraryName(libname); } + + /** + * This is a specialised <code>Collection</code>, providing + * the necessary provisions for the collections used by the + * environment variable map. Namely, it prevents + * querying anything but <code>String</code>s. + * + * @author Andrew John Hughes (gnu...@me...) + */ + private static class EnvironmentCollection + extends AbstractCollection<String> + { + + /** + * The wrapped collection. + */ + protected Collection<String> c; + + /** + * Constructs a new environment collection, which + * wraps the elements of the supplied collection. + * + * @param coll the collection to use as a base for + * this collection. + */ + public EnvironmentCollection(Collection<String> coll) + { + c = coll; + } + + /** + * Blocks queries containing a null object or an object which + * isn't of type <code>String</code>. All other queries + * are forwarded to the underlying collection. + * + * @param obj the object to look for. + * @return true if the object exists in the collection. + * @throws NullPointerException if the specified object is null. + * @throws ClassCastException if the specified object is not a String. + */ + public boolean contains(Object obj) + { + if (obj == null) + throw new + NullPointerException("This collection does not support " + + "null values."); + if (!(obj instanceof String)) + throw new + ClassCastException("This collection only supports Strings."); + return c.contains(obj); + } + + /** + * Blocks queries where the collection contains a null object or + * an object which isn't of type <code>String</code>. All other + * queries are forwarded to the underlying collection. + * + * @param coll the collection of objects to look for. + * @return true if the collection contains all elements in the collection. + * @throws NullPointerException if the collection is null. + * @throws NullPointerException if any collection entry is null. + * @throws ClassCastException if any collection entry is not a String. + */ + public boolean containsAll(Collection<?> coll) + { + for (Object o: coll) + { + if (o == null) + throw new + NullPointerException("This collection does not support " + + "null values."); + if (!(o instanceof String)) + throw new + ClassCastException("This collection only supports Strings."); + } + return c.containsAll(coll); + } + + /** + * This returns an iterator over the map elements, with the + * same provisions as for the collection and underlying map. + * + * @return an iterator over the map elements. + */ + public Iterator<String> iterator() + { + return c.iterator(); + } + + /** + * Blocks the removal of elements from the collection. + * + * @return true if the removal was sucessful. + * @throws NullPointerException if the collection is null. + * @throws NullPointerException if any collection entry is null. + * @throws ClassCastException if any collection entry is not a String. + */ + public boolean remove(Object key) + { + if (key == null) + throw new + NullPointerException("This collection does not support " + + "null values."); + if (!(key instanceof String)) + throw new + ClassCastException("This collection only supports Strings."); + return c.contains(key); + } + + /** + * Blocks the removal of all elements in the specified + * collection from the collection. + * + * @param coll the collection of elements to remove. + * @return true if the elements were removed. + * @throws NullPointerException if the collection is null. + * @throws NullPointerException if any collection entry is null. + * @throws ClassCastException if any collection entry is not a String. + */ + public boolean removeAll(Collection<?> coll) + { + for (Object o: coll) + { + if (o == null) + throw new + NullPointerException("This collection does not support " + + "null values."); + if (!(o instanceof String)) + throw new + ClassCastException("This collection only supports Strings."); + } + return c.removeAll(coll); + } + + /** + * Blocks the retention of all elements in the specified + * collection from the collection. + * + * @param c the collection of elements to retain. + * @return true if the other elements were removed. + * @throws NullPointerException if the collection is null. + * @throws NullPointerException if any collection entry is null. + * @throws ClassCastException if any collection entry is not a String. + */ + public boolean retainAll(Collection<?> coll) + { + for (Object o: coll) + { + if (o == null) + throw new + NullPointerException("This collection does not support " + + "null values."); + if (!(o instanceof String)) + throw new + ClassCastException("This collection only supports Strings."); + } + return c.containsAll(coll); + } + + /** + * This simply calls the same method on the wrapped + * collection. + * + * @return the size of the underlying collection. + */ + public int size() + { + return c.size(); + } + + } // class EnvironmentCollection<String> + + /** + * This is a specialised <code>HashMap</code>, which + * prevents the addition or querying of anything other than + * <code>String</code> objects. + * + * @author Andrew John Hughes (gnu...@me...) + */ + static class EnvironmentMap + extends HashMap<String,String> + { + + /** + * Cache the entry set. + */ + private transient Set<Map.Entry<String,String>> entries; + + /** + * Cache the key set. + */ + private transient Set<String> keys; + + /** + * Cache the value collection. + */ + private transient Collection<String> values; + + /** + * Constructs a new empty <code>EnvironmentMap</code>. + */ + EnvironmentMap() + { + super(); + } + + /** + * Constructs a new <code>EnvironmentMap</code> containing + * the contents of the specified map. + * + * @param m the map to be added to this. + * @throws NullPointerException if a key or value is null. + * @throws ClassCastException if a key or value is not a String. + */ + EnvironmentMap(Map<String,String> m) + { + super(m); + } + + /** + * Blocks queries containing a null key or one which is not + * of type <code>String</code>. All other queries + * are forwarded to the superclass. + * + * @param key the key to look for in the map. + * @return true if the key exists in the map. + * @throws NullPointerException if the specified key is null. + */ + public boolean containsKey(Object key) + { + if (key == null) + throw new + NullPointerException("This map does not support null keys."); + if (!(key instanceof String)) + throw new + ClassCastException("This map only allows queries using Strings."); + return super.containsKey(key); + } + + /** + * Blocks queries using a null or non-<code>String</code> value. + * All other queries are forwarded to the superclass. + * + * @param value the value to look for in the map. + * @return true if the value exists in the map. + * @throws NullPointerException if the specified value is null. + */ + public boolean containsValue(Object value) + { + if (value == null) + throw new + NullPointerException("This map does not support null values."); + if (!(value instanceof String)) + throw new + ClassCastException("This map only allows queries using Strings."); + return super.containsValue(value); + } + + /** + * Returns a set view of the map entries, with the same + * provisions as for the underlying map. + * + * @return a set containing the map entries. + */ + public Set<Map.Entry<String,String>> entrySet() + { + if (entries == null) + entries = super.entrySet(); + return entries; + } + + /** + * Blocks queries containing a null or non-<code>String</code> key. + * All other queries are passed on to the superclass. + * + * @param key the key to retrieve the value for. + * @return the value associated with the given key. + * @throws NullPointerException if the specified key is null. + * @throws ClassCastException if the specified key is not a String. + */ + public String get(Object key) + { + if (key == null) + throw new + NullPointerException("This map does not support null keys."); + if (!(key instanceof String)) + throw new + ClassCastException("This map only allows queries using Strings."); + return super.get(key); + } + + /** + * Returns a set view of the keys, with the same + * provisions as for the underlying map. + * + * @return a set containing the keys. + */ + public Set<String> keySet() + { + if (keys == null) + keys = new EnvironmentSet(super.keySet()); + return keys; + } + + /** + * Associates the given key to the given value. If the + * map already contains the key, its value is replaced. + * The map does not accept null keys or values, or keys + * and values not of type {@link String}. + * + * @param key the key to map. + * @param value the value to be mapped. + * @return the previous value of the key, or null if there was no mapping + * @throws NullPointerException if a key or value is null. + * @throws ClassCastException if a key or value is not a String. + */ + public String put(String key, String value) + { + if (key == null) + throw new NullPointerException("A new key is null."); + if (value == null) + throw new NullPointerException("A new value is null."); + if (!(key instanceof String)) + throw new ClassCastException("A new key is not a String."); + if (!(value instanceof String)) + throw new ClassCastException("A new value is not a String."); + return super.put(key, value); + } + + /** + * Removes a key-value pair from the map. The queried key may not + * be null or of a type other than a <code>String</code>. + * + * @param key the key of the entry to remove. + * @return the removed value. + * @throws NullPointerException if the specified key is null. + * @throws ClassCastException if the specified key is not a String. + */ + public String remove(Object key) + { + if (key == null) + throw new + NullPointerException("This map does not support null keys."); + if (!(key instanceof String)) + throw new + ClassCastException("This map only allows queries using Strings."); + return super.remove(key); + } + + /** + * Returns a collection view of the values, with the same + * provisions as for the underlying map. + * + * @return a collection containing the values. + */ + public Collection<String> values() + { + if (values == null) + values = new EnvironmentCollection(super.values()); + return values; + } + + } + + /** + * This is a specialised <code>Set</code>, providing + * the necessary provisions for the collections used by the + * environment variable map. Namely, it prevents + * modifications and the use of queries with null + * or non-<code>String</code> values. + * + * @author Andrew John Hughes (gnu...@me...) + */ + private static class EnvironmentSet + extends EnvironmentCollection + implements Set<String> + { + + /** + * Constructs a new environment set, which + * wraps the elements of the supplied set. + * + * @param set the set to use as a base for + * this set. + */ + public EnvironmentSet(Set<String> set) + { + super(set); + } + + /** + * This simply calls the same method on the wrapped + * collection. + * + * @param obj the object to compare with. + * @return true if the two objects are equal. + */ + public boolean equals(Object obj) + { + return c.equals(obj); + } + + /** + * This simply calls the same method on the wrapped + * collection. + * + * @return the hashcode of the collection. + */ + public int hashCode() + { + return c.hashCode(); + } + + } // class EnvironmentSet<String> + } // class System Added: trunk/core/src/classpath/java/java/lang/management/LockInfo.java =================================================================== --- trunk/core/src/classpath/java/java/lang/management/LockInfo.java (rev 0) +++ trunk/core/src/classpath/java/java/lang/management/LockInfo.java 2007-01-07 12:53:02 UTC (rev 3022) @@ -0,0 +1,114 @@ +/* LockInfo.java - Information on a lock. + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang.management; + +import java.beans.ConstructorProperties; + +/** + * Provides information on a lock held by a thread. + * A lock can be either a built-in monitor, an + * <emph>ownable synchronizer</emph> (i.e. a subclass + * of {@link java.util.concurrent.locks.AbstractOwnableSynchronizer}), + * or a {@link java.util.concurrent.locks.Condition} + * object. + * + * @author Andrew John Hughes (gnu...@me...) + * @since 1.6 + */ +public class LockInfo +{ + + /** + * The class name of the lock object. + */ + private String className; + + /** + * The identity hash code of the lock object. + */ + private int identityHashCode; + + /** + * Constructs a new {@link LockInfo} object with the + * specified class name and identity hash code. + * + * @param className the name of the class of the lock object. + * @param identityHashCode the identity hash code of the + * lock object. + */ + @ConstructorProperties({"className","identityHashCode"}) + public LockInfo(String className, int identityHashCode) + { + this.className = className; + this.identityHashCode = identityHashCode; + } + + /** + * Returns the class name of the lock object. + * + * @return the class name of the lock object. + */ + public String getClassName() + { + return className; + } + + /** + * Returns the identity hash code of the lock object. + * + * @return the identity hash code of the lock object. + */ + public int getIdentityHashCode() + { + return identityHashCode; + } + + /** + * Returns a textual representation of the lock, + * constructed by concatenating the class name, + * <code>'@'</code> and the identity hash code + * in unsigned hexadecimal form. + * + * @return a textual representation of the lock. + */ + public String toString() + { + return className + '@' + Integer.toHexString(identityHashCode); + } + +} Modified: trunk/core/src/classpath/java/java/lang/management/ManagementFactory.java =================================================================== --- trunk/core/src/classpath/java/java/lang/management/ManagementFactory.java 2007-01-07 12:51:25 UTC (rev 3021) +++ trunk/core/src/classpath/java/java/lang/management/ManagementFactory.java 2007-01-07 12:53:02 UTC (rev 3022) @@ -49,11 +49,36 @@ import gnu.java.lang.management.RuntimeMXBeanImpl; import gnu.java.lang.management.ThreadMXBeanImpl; +import java.io.IOException; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.logging.LogManager; + +import javax.management.Attribute; +import javax.management.InstanceAlreadyExistsException; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServer; +import javax.management.MBeanServerConnection; +import javax.management.MBeanServerFactory; +import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; +import javax.management.NotificationEmitter; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.ObjectName; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.TabularData; + /** * <p> * Provides access to the system's management beans via a series @@ -66,6 +91,11 @@ * <ol> * <li>Calling the appropriate static method of this factory. * </li> + * <li>Using the platform {@link javax.management.MBeanServer} + * to access the beans locally, or an + * {@link javax.management.MBeanServerConnection} for remote + * access. The attributes and operations use the limited + * range of data types specified below.</li> * </ol> * <h2>Open Data Types</h2> * <p> @@ -118,6 +148,60 @@ { /** + * The object name for the class loading bean. + */ + public static final String CLASS_LOADING_MXBEAN_NAME = + "java.lang:type=ClassLoading"; + + /** + * The object name for the compilation bean. + */ + public static final String COMPILATION_MXBEAN_NAME = + "java.lang:type=Compilation"; + + /** + * The domain for the garbage collecting beans. + */ + public static final String GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE = + "java.lang:type=GarbageCollector"; + + /** + * The domain for the memory manager beans. + */ + public static final String MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE = + "java.lang:type=MemoryManager"; + + /** + * The object name for the memory bean. + */ + public static final String MEMORY_MXBEAN_NAME = + "java.lang:type=Memory"; + + /** + * The domain for the memory pool beans. + */ + public static final String MEMORY_POOL_MXBEAN_DOMAIN_TYPE = + "java.lang:type=MemoryPool"; + + /** + * The object name for the operating system bean. + */ + public static final String OPERATING_SYSTEM_MXBEAN_NAME = + "java.lang:type=OperatingSystem"; + + /** + * The object name for the runtime bean. + */ + public static final String RUNTIME_MXBEAN_NAME = + "java.lang:type=Runtime"; + + /** + * The object name for the threading bean. + */ + public static final String THREAD_MXBEAN_NAME = + "java.lang:type=Threading"; + + /** * The operating system management bean. */ private static OperatingSystemMXBean osBean; @@ -148,6 +232,11 @@ private static CompilationMXBean compilationBean; /** + * The platform server. + */ + private static MBeanServer platformServer; + + /** * Private constructor to prevent instance creation. */ private ManagementFactory() {} @@ -301,9 +390,10 @@ * * @return a list of memory pool beans, one for each pool. */ - public static List getMemoryPoolMXBeans() + public static List<MemoryPoolMXBean> getMemoryPoolMXBeans() { - List poolBeans = new ArrayList(); + List<MemoryPoolMXBean> poolBeans = + new ArrayList<MemoryPoolMXBean>(); String[] names = VMManagementFactory.getMemoryPoolNames(); for (int a = 0; a < names.length; ++a) try @@ -326,9 +416,10 @@ * * @return a list of memory manager beans, one for each manager. */ - public static List getMemoryManagerMXBeans() + public static List<MemoryManagerMXBean> getMemoryManagerMXBeans() { - List managerBeans = new ArrayList(); + List<MemoryManagerMXBean> managerBeans = + new ArrayList<MemoryManagerMXBean>(); String[] names = VMManagementFactory.getMemoryManagerNames(); for (int a = 0; a < names.length; ++a) try @@ -352,9 +443,10 @@ * * @return a list of garbage collector beans, one for each pool. */ - public static List getGarbageCollectorMXBeans() + public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() { - List gcBeans = new ArrayList(); + List<GarbageCollectorMXBean> gcBeans = + new ArrayList<GarbageCollectorMXBean>(); String[] names = VMManagementFactory.getGarbageCollectorNames(); for (int a = 0; a < names.length; ++a) try @@ -371,4 +463,355 @@ return gcBeans; } + /** + * <p> + * Returns the platform {@link javax.management.MBeanServer}. On the + * first call to this method, a server instance is retrieved from + * the {@link javax.management.MBeanServerFactory} and each of the + * beans are registered with it. Subsequent calls return the existing + * instance. If the property <code>javax.management.builder.initial</code> + * is set, its value will be used as the name of the class which is used + * to provide the server instance. + * </p> + * <p> + * It is recommended that the platform server is used for other beans as + * well, in order to simplify their discovery and publication. Name conflicts + * should be avoided. + * </p> + * + * @return the platform {@link javax.management.MBeanServer} + * @throws SecurityException if a security manager exists and the + * caller's permissions don't imply {@link + * MBeanServerPermission(String)}("createMBeanServer") + * @see javax.management.MBeanServerFactory + * @see javax.management.MBeanServerFactory#createMBeanServer() + */ + public static MBeanServer getPlatformMBeanServer() + { + if (platformServer == null) + { + platformServer = MBeanServerFactory.createMBeanServer(); + try + { + platformServer.registerMBean(getOperatingSystemMXBean(), + new ObjectName(OPERATING_SYSTEM_MXBEAN_NAME)); + platformServer.registerMBean(getRuntimeMXBean(), + new ObjectName(RUNTIME_MXBEAN_NAME)); + platformServer.registerMBean(getClassLoadingMXBean(), + new ObjectName(CLASS_LOADING_MXBEAN_NAME)); + platformServer.registerMBean(getThreadMXBean(), + new ObjectName(THREAD_MXBEAN_NAME)); + platformServer.registerMBean(getMemoryMXBean(), + new ObjectName(MEMORY_MXBEAN_NAME)); + CompilationMXBean compBean = getCompilationMXBean(); + if (compBean != null) + platformServer.registerMBean(compBean, + new ObjectName(COMPILATION_MXBEAN_NAME)); + Iterator beans = getMemoryPoolMXBeans().iterator(); + while (beans.hasNext()) + { + MemoryPoolMXBean bean = (MemoryPoolMXBean) beans.next(); + platformServer.registerMBean(bean, + new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE + + ",name=" + + bean.getName())); + } + beans = getMemoryManagerMXBeans().iterator(); + while (beans.hasNext()) + { + MemoryManagerMXBean bean = (MemoryManagerMXBean) beans.next(); + platformServer.registerMBean(bean, + new ObjectName(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE + + ",name=" + + bean.getName())); + } + beans = getGarbageCollectorMXBeans().iterator(); + while (beans.hasNext()) + { + GarbageCollectorMXBean bean = (GarbageCollectorMXBean) beans.next(); + platformServer.registerMBean(bean, + new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + + ",name=" + + bean.getName())); + } + platformServer.registerMBean(LogManager.getLoggingMXBean(), + new ObjectName(LogManager.LOGGING_MXBEAN_NAME)); + } + catch (InstanceAlreadyExistsException e) + { + throw (Error) + (new InternalError("One of the management beans is " + + "already registered.").initCause(e)); + } + catch (MBeanRegistrationException e) + { + throw (Error) + (new InternalError("One of the management beans' preRegister " + + "methods threw an exception.").initCause(e)); + } + catch (NotCompliantMBeanException e) + { + throw (Error) + (new InternalError("One of the management beans is " + + "not compliant.").initCause(e)); + } + catch (MalformedObjectNameException e) + { + throw (Error) + (new InternalError("The object name of a management bean is " + + "not compliant.").initCause(e)); + } + } + return platformServer; + } + + /** + * <p> + * Returns a proxy for the specified platform bean. A proxy object is created + * using <code>Proxy.newProxyInstance(mxbeanInterface.getClassLoader(), + * new Class[] { mxbeanInterface }, handler)</code>. The + * {@link javax.management.NotificationEmitter} class is also added to the + * array if the bean provides notifications. <code>handler</code> refers + * to the invocation handler which forwards calls to the connection, and + * also provides translation between the Java data types used in the + * bean interfaces and the open data types, as specified in the description + * of this class. It is this translation that makes the + * usual {@link javax.management.MBeanServerInvocationHandler} inappropriate + * for providing such a proxy. + * </p> + * <p> + * <strong>Note</strong>: use of the proxy may result in + * {@link java.io.IOException}s from the underlying {@link MBeanServerConnection} + * and a {@link java.io.InvalidObjectException} if enum constants + * used on the client and the server don't match. + * </p> + * + * @param connection the server connection to use to access the bean. + * @param mxbeanName the {@link javax.management.ObjectName} of the + * bean to provide a proxy for. + * @param mxbeanInterface the interface for the bean being proxied. + * @return a proxy for the specified bean. + * @throws IllegalArgumentException if <code>mxbeanName</code> is not a valid + * {@link javax.management.ObjectName}, + * the interface and name do not match the + * same bean, the name does not refer to a + * platform bean or the bean is not registered + * with the server accessed by <code>connection</code>. + * @throws IOException if the connection throws one. + */ + public static <T> T newPlatformMXBeanProxy(MBeanServerConnection connection, + String mxbeanName, + Class<T> mxbeanInterface) + throws IOException + { + if (!(mxbeanName.equals(CLASS_LOADING_MXBEAN_NAME) || + mxbeanName.equals(COMPILATION_MXBEAN_NAME) || + mxbeanName.startsWith(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE) || + mxbeanName.startsWith(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE) || + mxbeanName.equals(MEMORY_MXBEAN_NAME) || + mxbeanName.startsWith(MEMORY_POOL_MXBEAN_DOMAIN_TYPE) || + mxbeanName.equals(OPERATING_SYSTEM_MXBEAN_NAME) || + mxbeanName.equals(RUNTIME_MXBEAN_NAME) || + mxbeanName.equals(THREAD_MXBEAN_NAME))) + { + throw new IllegalArgumentException("The named bean, " + mxbeanName + + ", is not a platform name."); + } + if ((mxbeanName.equals(CLASS_LOADING_MXBEAN_NAME) && + mxbeanInterface != ClassLoadingMXBean.class) || + (mxbeanName.equals(COMPILATION_MXBEAN_NAME) && + mxbeanInterface != CompilationMXBean.class) || + (mxbeanName.startsWith(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE) && + mxbeanInterface != GarbageCollectorMXBean.class) || + (mxbeanName.startsWith(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE) && + mxbeanInterface != MemoryManagerMXBean.class) || + (mxbeanName.equals(MEMORY_MXBEAN_NAME) && + mxbeanInterface != MemoryMXBean.class) || + (mxbeanName.startsWith(MEMORY_POOL_MXBEAN_DOMAIN_TYPE) && + mxbeanInterface != MemoryPoolMXBean.class) || + (mxbeanName.equals(OPERATING_SYSTEM_MXBEAN_NAME) && + mxbeanInterface != OperatingSystemMXBean.class) || + (mxbeanName.equals(RUNTIME_MXBEAN_NAME) && + mxbeanInterface != RuntimeMXBean.class) || + (mxbeanName.equals(THREAD_MXBEAN_NAME) && + mxbeanInterface != ThreadMXBean.class)) + throw new IllegalArgumentException("The interface, " + mxbeanInterface + + ", does not match the bean, " + mxbeanName); + ObjectName bean; + try + { + bean = new ObjectName(mxbeanName); + } + catch (MalformedObjectNameException e) + { + throw new IllegalArgumentException("The named bean is invalid."); + } + if (!(connection.isRegistered(bean))) + throw new IllegalArgumentException("The bean is not registered on this connection."); + Class[] interfaces; + if (mxbeanName.equals(MEMORY_MXBEAN_NAME)) + interfaces = new Class[] { mxbeanInterface, NotificationEmitter.class }; + else + interfaces = new Class[] { mxbeanInterface }; + return (T) Proxy.newProxyInstance(mxbeanInterface.getClassLoader(), + interfaces, + new ManagementInvocationHandler(connection, bean)); + } + + /** + * This invocation handler provides method calls for a platform bean + * by forwarding them to a {@link MBeanServerConnection}. Translation from + * Java data types to open data types is performed as specified above. + * + * @author Andrew John Hughes (gnu...@me...) + * @since 1.5 + */ + private static class ManagementInvocationHandler + implements InvocationHandler + { + + /** + * The encapsulated connection. + */ + private MBeanServerConnection conn; + + /** + * The bean being proxied. + */ + private ObjectName bean; + + /** + * Constructs a new {@link InvocationHandler} which proxies + * for the specified bean using the supplied connection. + * + * @param conn the connection on which to forward method calls. + * @param bean the bean to proxy. + */ + public ManagementInvocationHandler(MBeanServerConnection conn, + ObjectName bean) + throws IOException + { + this.conn = conn; + this.bean = bean; + } + + /** + * Called by the proxy class whenever a method is called. The method + * is emulated by retrieving an attribute from, setting an attribute on + * or invoking a method on the server connection as required. Translation + * between the Java data types supplied as arguments to the open types used + * by the bean is provided, as well as translation of the return value back + * in to the appropriate Java type. + * + * @param proxy the proxy on which the method was called. + * @param method the method which was called. + * @param args the arguments supplied to the method. + * @return the return value from the method. + * @throws Throwable if an exception is thrown in performing the + * method emulation. + */ + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable + { + String name = method.getName(); + if (name.equals("toString")) + return "Proxy for " + bean + " using " + conn; + if (name.equals("addNotificationListener")) + { + conn.addNotificationListener(bean, + (NotificationListener) args[0], + (NotificationFilter) args[1], + args[2]); + return null; + } + if (name.equals("getNotificationInfo")) + return conn.getMBeanInfo(bean).getNotifications(); + if (name.equals("removeNotificationListener")) + { + if (args.length == 1) + conn.removeNotificationListener(bean, + (NotificationListener) + args[0]); + else + conn.removeNotificationListener(bean, + (NotificationListener) + args[0], + (NotificationFilter) + args[1], args[2]); + return null; + } + String attrib = null; + if (name.startsWith("get")) + attrib = name.substring(3); + else if (name.startsWith("is")) + attrib = name.substring(2); + if (attrib != null) + return translate(conn.getAttribute(bean, attrib), method); + else if (name.startsWith("set")) + { + conn.setAttribute(bean, new Attribute(name.substring(3), + args[0])); + return null; + } + else + return translate(conn.invoke(bean, name, args, null), method); + } + + /** + * Translates the returned open data type to the value + * required by the interface. + * + * @param otype the open type returned by the method call. + * @param method the method that was called. + * @return the equivalent return type required by the interface. + * @throws Throwable if an exception is thrown in performing the + * conversion. + */ + private final Object translate(Object otype, Method method) + throws Throwable + { + Class<?> returnType = method.getReturnType(); + if (returnType.isEnum()) + { + String ename = (String) otype; + Enum[] constants = (Enum[]) returnType.getEnumConstants(); + for (Enum c : constants) + if (c.name().equals(ename)) + return c; + } + if (List.class.isAssignableFrom(returnType)) + { + Object[] elems = (Object[]) otype; + List l = new ArrayList(elems.length); + for (Object elem : elems) + l.add(elem); + return l; + } + if (Map.class.isAssignableFrom(returnType)) + { + TabularData data = (TabularData) otype; + Map m = new HashMap(data.size()); + for (Object val : data.values()) + { + CompositeData vals = (CompositeData) val; + m.put(vals.get("key"), vals.get("value")); + } + return m; + } + try + { + Method m = returnType.getMethod("from", + new Class[] + { CompositeData.class }); + return m.invoke(null, (CompositeData) otype); + } + catch (NoSuchMethodException e) + { + /* Ignored; we expect this if this + isn't a from(CompositeData) class */ + } + return otype; + } + + } } Modified: trunk/core/src/classpath/java/java/lang/management/MemoryPoolMXBean.java =================================================================== --- trunk/core/src/classpath/java/java/lang/management/MemoryPoolMXBean.java 2007-01-07 12:51:25 UTC (rev 3021) +++ trunk/core/src/classpath/java/java/lang/management/MemoryPoolMXBean.java 2007-01-07 12:53:02 UTC (rev 3022) @@ -162,7 +162,7 @@ * * @return the type of this pool. */ - String getType(); + MemoryType getType(); /** * Returns memory usage statistics for the current memory usage Added: trunk/core/src/classpath/java/java/lang/management/MemoryType.java =================================================================== --- trunk/core/src/classpath/java/java/lang/management/MemoryType.java (rev 0) +++ trunk/core/src/classpath/java/java/lang/management/MemoryType.java 2007-01-07 12:53:02 UTC (rev 3022) @@ -0,0 +1,51 @@ +/* MemoryType.java - Enumeration of the types of memory pools. + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang.management; + +/** + * Enumerates the possible types of memory pools. A value of this + * type is returned by {@link MemoryPoolMXBean#getMemoryType()}. + * + * @author Andrew John Hughes (gnu...@me...) + * @since 1.5 + */ +public enum MemoryType +{ + HEAP, NON_HEAP; +} + Modified: trunk/core/src/classpath/java/java/lang/management/MemoryUsage.java =================================================================== --- trunk/core/src/classpath/java/java/lang/management/MemoryUsage.java 2007-01-07 12:51:25 UTC (rev 3021) +++ trunk/core/src/classpath/java/java/lang/management/MemoryUsage.java 2007-01-07 12:53:02 UTC (rev 3022) @@ -180,14 +180,14 @@ if (data == null) return null; CompositeType type = data.getCompositeType(); - ThreadInfo.checkAttribute(type, "init", SimpleType.LONG); - ThreadInfo.checkAttribute(type, "used", SimpleType.LONG); - ThreadInfo.checkAttribute(type, "committed", SimpleType.LONG); - ThreadInfo.checkAttribute(type, "max", SimpleType.LONG); - return new MemoryUsage(((Long) data.get("init")).longValue(), - ((Long) data.get("used")).longValue(), - ((Long) data.get("committed")).longValue(), - ((Long) data.get("max")).longValue()); + ThreadInfo.checkAttribute(type, "Init", SimpleType.LONG); + ThreadInfo.checkAttribute(type, "Used", SimpleType.LONG); + ThreadInfo.checkAttribute(type, "Committed", SimpleType.LONG); + ThreadInfo.checkAttribute(type, "Max", SimpleType.LONG); + return new MemoryUsage(((Long) data.get("Init")).longValue(), + ((Long) data.get("Used")).longVa... [truncated message content] |
From: <ls...@us...> - 2007-01-07 12:51:26
|
Revision: 3021 http://jnode.svn.sourceforge.net/jnode/?rev=3021&view=rev Author: lsantha Date: 2007-01-07 04:51:25 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PrivateCredentials.java Added Paths: ----------- trunk/core/src/classpath/gnu/gnu/javax/crypto/key/GnuPBEKey.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/AbstractSessionContext.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PreSharedKeyManager.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PreSharedKeyManagerParameters.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLCipherSuite.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLProtocolVersion.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLRecordHandler.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/Session.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SessionStoreException.java trunk/core/src/classpath/gnu/gnu/javax/security/auth/callback/CertificateCallback.java trunk/core/src/classpath/gnu/gnu/javax/swing/text/html/CharacterAttributeTranslator.java Removed Paths: ------------- trunk/core/src/classpath/gnu/gnu/javax/swing/text/html/parser/HTML_401Swing.java Added: trunk/core/src/classpath/gnu/gnu/javax/crypto/key/GnuPBEKey.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/crypto/key/GnuPBEKey.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/crypto/key/GnuPBEKey.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -0,0 +1,95 @@ +/* GnuPBEKey.java -- A password-based encryption key. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key; + +import javax.crypto.interfaces.PBEKey; +import javax.crypto.spec.PBEKeySpec; + +/** + * An implementation of a password-based encryption key. + * + * @author Casey Marshall (cs...@gn...) + */ +public class GnuPBEKey + implements PBEKey +{ + private final PBEKeySpec spec; + + public GnuPBEKey (final PBEKeySpec spec) + { + if (spec == null) + throw new NullPointerException (); + this.spec = spec; + } + + public GnuPBEKey (char[] password, byte[] salt, int iterationCount) + { + this (new PBEKeySpec (password, salt, iterationCount)); + } + + public int getIterationCount () + { + return spec.getIterationCount (); + } + + public char[] getPassword () + { + return spec.getPassword (); + } + + public byte[] getSalt () + { + return spec.getSalt (); + } + + public String getAlgorithm () + { + return "PBE"; + } + + public String getFormat () + { + return "NONE"; // FIXME? + } + + public byte[] getEncoded () + { + return null; // FIXME? + } +} Added: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/AbstractSessionContext.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/AbstractSessionContext.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/AbstractSessionContext.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -0,0 +1,288 @@ +/* AbstractSessionContext -- stores SSL sessions, possibly persistently. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.net.ssl; + +import gnu.java.security.Requires; + +import gnu.javax.net.ssl.provider.SimpleSessionContext; + +import java.util.Enumeration; + +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLPermission; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSessionContext; + +/** + * A skeletal implementation of {@link SSLSessionContext}. This class may + * be subclassed to add extended functionality to session contexts, such + * as by storing sessions in files on disk, or by sharing contexts + * across different JVM instances. + * + * <p>In order to securely store sessions, along with private key data, + * the abstract methods {@lnk {@link #load(char[])} and {@link #store(char[])} + * come into play. When storing sessions, a session context implementation + * must pass this password to the {@link Session#prepare(char[])} method, + * before either writing the {@link java.io.Serializable} session to the + * underlying store, or getting the opaque {@link Session#privateData()} + * class from the session, and storing that. + * + * <p>As a simple example, that writes sessions to some object output + * stream: + * + * <pre> + char[] password = ...; + ObjectOutputStream out = ...; + ... + for (Session s : this) + { + s.prepare(password); + out.writeObject(s); + }</pre> + * + * <p>The reverse must be done when deserializing sessions, by using the + * {@link Session#repair(char[])} method, possibly by first calling + * {@link Session#setPrivateData(java.io.Serializable)} with the read, + * opaque private data type. Thus an example of reading may be: + * + * <pre> + char[] password = ...; + ObjectInputStream in = ...; + ... + while (hasMoreSessions(in)) + { + Session s = (Session) in.readObject(); + s.repair(password); + addToThisStore(s); + }</pre> + * + * @author Casey Marshall (cs...@gn...) + */ +public abstract class AbstractSessionContext implements SSLSessionContext +{ + protected long timeout; + private static Class<? extends AbstractSessionContext> + implClass = SimpleSessionContext.class; + + /** + * Create a new instance of a session context, according to the configured + * implementation class. + * + * @return The new session context. + * @throws SSLException If an error occurs in creating the instance. + */ + public static AbstractSessionContext newInstance () throws SSLException + { + try + { + return implClass.newInstance(); + } + catch (IllegalAccessException iae) + { + throw new SSLException(iae); + } + catch (InstantiationException ie) + { + throw new SSLException(ie); + } + } + + /** + * Reconfigure this instance to use a different session context + * implementation. + * + * <p><strong>Note:</strong> this method requires that the caller have + * {@link SSLPermission} with target + * <code>gnu.javax.net.ssl.AbstractSessionContext</code> and action + * <code>setImplClass</code>. + * + * @param clazz The new implementation class. + * @throws SecurityException If the caller does not have permission to + * change the session context. + */ + @Requires(permissionClass = SSLPermission.class, + target = "gnu.javax.net.ssl.AbstractSessionContext", + action = "setImplClass") + public static synchronized void setImplClass + (Class<? extends AbstractSessionContext> clazz) + throws SecurityException + { + SecurityManager sm = System.getSecurityManager (); + if (sm != null) + sm.checkPermission(new SSLPermission("gnu.javax.net.ssl.AbstractSessionContext", + "setImplClass")); + implClass = clazz; + } + + /** + * @param timeout The initial session timeout. + */ + protected AbstractSessionContext (final int timeout) + { + setSessionTimeout(timeout); + } + + /** + * Fetch a saved session by its ID. This method will (possibly) + * deserialize and return the SSL session with that ID, or null if + * the requested session does not exist, or has expired. + * + * <p>Subclasses implementing this class <strong>must not</strong> + * perform any blocking operations in this method. If any blocking + * behavior is required, it must be done in the {@link load(char[])} + * method. + * + * @param sessionId The ID of the session to get. + * @return The found session, or null if no such session was found, + * or if that session has expired. + */ + public final SSLSession getSession (byte[] sessionId) + { + Session s = implGet (sessionId); + if (s != null + && System.currentTimeMillis () - s.getLastAccessedTime () > timeout) + { + remove (sessionId); + return null; + } + return s; + } + + public final SSLSession getSession(String host, int port) + { + for (Enumeration e = getIds(); e.hasMoreElements(); ) + { + byte[] id = (byte[]) e.nextElement(); + SSLSession s = getSession(id); + if (s == null) // session expired. + continue; + String host2 = s.getPeerHost(); + if (host == null) + { + if (host2 != null) + continue; + } + else if (!host.equals(host2)) + continue; + int port2 = s.getPeerPort(); + if (port != port2) + continue; + + // Else, a match. + return s; + } + + return null; + } + + /** + * To be implemented by subclasses. Subclasses do not need to check + * timeouts in this method. + * + * @param sessionId The session ID. + * @return The session, or <code>null</code> if the requested session + * was not found. + */ + protected abstract Session implGet (byte[] sessionId); + + public int getSessionTimeout() + { + return (int) (timeout / 1000); + } + + /** + * Load this session store from the underlying media, if supported + * by the implementation. + * + * @param password The password that protects the sensitive data in + * this store. + * @throws SessionStoreException If reading this store fails, such + * as when an I/O exception occurs, or if the password is incorrect. + */ + public abstract void load (char[] password) throws SessionStoreException; + + /** + * Add a new session to the store. The underlying implementation + * will add the session to its store, possibly overwriting any + * existing session with the same ID. + * + * <p>Subclasses implementing this class <strong>must not</strong> + * perform any blocking operations in this method. If any blocking + * behavior is required, it must be done in the {@link + * #store(char[])} method. + * + * @param session The session to add. + * @throws NullPointerException If the argument is null. + */ + public abstract void put (Session session); + + /** + * Remove a session from this store. + * + * <p>Subclasses implementing this class <strong>must not</strong> + * perform any blocking operations in this method. If any blocking + * behavior is required, it must be done in the {@link + * #store(char[])} method. + * + * @param sessionId The ID of the session to remove. + */ + public abstract void remove (byte[] sessionId); + + /** + * + */ + public final void setSessionTimeout(int seconds) + { + if (timeout < 0) + throw new IllegalArgumentException("timeout may not be negative"); + this.timeout = (long) seconds * 1000; + } + + /** + * Commit this session store to the underlying media. For session + * store implementations that support saving sessions across + * invocations of the JVM, this method will save any sessions that + * have not expired to some persistent media, so they may be loaded + * and used again later. + * + * @param password The password that will protect the sensitive data + * in this store. + */ + public abstract void store (char[] password) throws SessionStoreException; +} \ No newline at end of file Added: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PreSharedKeyManager.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PreSharedKeyManager.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PreSharedKeyManager.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -0,0 +1,54 @@ +/* PreSharedKeyManager.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.net.ssl; + +import java.security.KeyManagementException; + +import javax.crypto.SecretKey; +import javax.net.ssl.KeyManager; + +/** + * @author Casey Marshall (cs...@gn...) + */ +public interface PreSharedKeyManager extends KeyManager +{ + SecretKey getKey(String name) throws KeyManagementException; + + String chooseIdentityHint(); +} \ No newline at end of file Added: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PreSharedKeyManagerParameters.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PreSharedKeyManagerParameters.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PreSharedKeyManagerParameters.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -0,0 +1,83 @@ +/* PreSharedKeyManagerParameters.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.net.ssl; + +import java.util.Iterator; +import java.util.LinkedHashMap; + +import javax.crypto.SecretKey; +import javax.net.ssl.ManagerFactoryParameters; + +/** + * @author Casey Marshall (cs...@gn...) + */ +public class PreSharedKeyManagerParameters + implements ManagerFactoryParameters +{ + private final LinkedHashMap<String, SecretKey> keys; + + public PreSharedKeyManagerParameters() + { + keys = new LinkedHashMap<String, SecretKey>(); + } + + public SecretKey getKey(String name) + { + name.getClass(); + return keys.get(name); + } + + public void putKey(String name, SecretKey key) + { + name.getClass(); + key.getClass(); + keys.put(name, key); + } + + public boolean removeKey(String name) + { + name.getClass(); + return keys.remove(name) != null; + } + + public Iterator<String> identities() + { + return keys.keySet().iterator(); + } +} Modified: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PrivateCredentials.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PrivateCredentials.java 2007-01-07 12:50:40 UTC (rev 3020) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/PrivateCredentials.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -51,6 +51,7 @@ import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Security; +import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @@ -95,16 +96,16 @@ public static final String BEGIN_RSA = "-----BEGIN RSA PRIVATE KEY"; public static final String END_RSA = "-----END RSA PRIVATE KEY"; - private List privateKeys; - private List certChains; + private List<PrivateKey> privateKeys; + private List<X509Certificate[]> certChains; // Constructor. // ------------------------------------------------------------------------- public PrivateCredentials() { - privateKeys = new LinkedList(); - certChains = new LinkedList(); + privateKeys = new LinkedList<PrivateKey>(); + certChains = new LinkedList<X509Certificate[]>(); } // Instance methods. @@ -115,7 +116,7 @@ IOException, NoSuchAlgorithmException, WrongPaddingException { CertificateFactory cf = CertificateFactory.getInstance("X.509"); - Collection certs = cf.generateCertificates(certChain); + Collection<? extends Certificate> certs = cf.generateCertificates(certChain); X509Certificate[] chain = (X509Certificate[]) certs.toArray(new X509Certificate[0]); String alg = null; @@ -199,11 +200,12 @@ (BigInteger) der.read().getValue(), // d mod (q-1) (BigInteger) der.read().getValue()); // coefficient } + privateKeys.add(kf.generatePrivate(spec)); certChains.add(chain); } - public List getPrivateKeys() + public List<PrivateKey> getPrivateKeys() { if (isDestroyed()) { @@ -212,7 +214,7 @@ return privateKeys; } - public List getCertChains() + public List<X509Certificate[]> getCertChains() { return certChains; } Added: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLCipherSuite.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLCipherSuite.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLCipherSuite.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -0,0 +1,142 @@ +/* SSLCipherSuite.java -- an SSL cipher suite. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.net.ssl; + +import gnu.java.security.Engine; + +import java.lang.reflect.InvocationTargetException; +import java.nio.ByteBuffer; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; + +/** + * An SSL cipher suite. + */ +public abstract class SSLCipherSuite +{ + private static final String SERVICE = "SSLCipherSuite"; + private final String algorithm; + private final byte[] id; + private final SSLProtocolVersion version; + private Provider provider; + + protected SSLCipherSuite (final String algorithm, final byte[] id, + final SSLProtocolVersion version) + { + this.algorithm = algorithm; + if (id.length != 2) + throw new IllegalArgumentException ("cipher suite ID must be two bytes"); + this.id = (byte[]) id.clone (); + this.version = version; + } + + public static final SSLCipherSuite getInstance (SSLProtocolVersion version, byte[] id) + throws NoSuchAlgorithmException + { + return getInstance (version + "-" + ((id[0] & 0xFF) + "/" + (id[1] & 0xFF))); + } + + public static final SSLCipherSuite getInstance (SSLProtocolVersion version, + byte[] id, Provider provider) + throws NoSuchAlgorithmException + { + return getInstance (version + "-" + (id[0] & 0xFF) + "/" + (id[1] & 0xFF), provider); + } + + public static final SSLCipherSuite getInstance (String name) + throws NoSuchAlgorithmException + { + Provider[] providers = Security.getProviders (); + for (int i = 0; i < providers.length; i++) + { + try + { + return getInstance (name, providers[i]); + } + catch (NoSuchAlgorithmException nsae) + { + // Ignore. + } + } + + throw new NoSuchAlgorithmException (SERVICE + ": " + name); + } + + public static final SSLCipherSuite getInstance (String name, Provider provider) + throws NoSuchAlgorithmException + { + SSLCipherSuite suite = null; + try + { + suite = (SSLCipherSuite) Engine.getInstance (SERVICE, name, provider); + suite.provider = provider; + } + catch (InvocationTargetException ite) + { + // XXX + NoSuchAlgorithmException nsae = new NoSuchAlgorithmException (name); + nsae.initCause (ite); + throw nsae; + } + return suite; + } + + public final String getAlgorithm () + { + return algorithm; + } + + public final byte[] getId () + { + return (byte[]) id.clone (); + } + + public final Provider getProvider () + { + return provider; + } + + public final SSLProtocolVersion getProtocolVersion () + { + return version; + } + + public abstract void encipher (ByteBuffer in, ByteBuffer out); +} Added: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLProtocolVersion.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLProtocolVersion.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLProtocolVersion.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -0,0 +1,54 @@ +/* SSLProtocolVersion.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.net.ssl; + +public enum SSLProtocolVersion +{ + SSLv3 (3, 0), + TLSv1 (3, 1); + + public final int major; + public final int minor; + + private SSLProtocolVersion (int major, int minor) + { + this.major = major; + this.minor = minor; + } +} Added: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLRecordHandler.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLRecordHandler.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SSLRecordHandler.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -0,0 +1,101 @@ +/* SSLRecordHandler.java -- a class that handles SSL record layer messages. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.net.ssl; + +import java.nio.ByteBuffer; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLException; + +public abstract class SSLRecordHandler +{ + private final byte contentType; + + /** + * Create a new record handler for the given content type. + */ + protected SSLRecordHandler (final byte contentType) + { + this.contentType = contentType; + } + + /** + * Handle an SSL record layer message, encapsulated in the supplied + * input buffer, and writing any output bytes to the output + * buffer. The input buffer is always only limited to the bytes that + * encapsulate the <em>fragment</em> of the record layer message + * — that is, the content-type, version, and length fields are + * not present in the input buffer, and the limit of the input + * buffer is always only as large as the fragment. If the message + * being read is not contained entirely within the given buffer, + * then the implementation should cache the bytes read as input, and + * wait until subsequent calls finish the object being read. + * + * <p>Technically, we expect only APPLICATION messages to ever + * produce output, but do suppose that extensions to the SSL + * protocol could allow other channels that produce output. + * + * @param input The input buffer. + * @param output The output buffer. + */ + public abstract void handle (final ByteBuffer input, + final ByteBuffer output) + throws SSLException; + + /** + * Returns the record layer content type that this handler is for. + * + * @return The content type value. + */ + public final byte contentType () + { + return contentType; + } + + public boolean equals (final Object o) + { + if (!(o instanceof SSLRecordHandler)) + return false; + return ((SSLRecordHandler) o).contentType == contentType; + } + + public int hashCode () + { + return contentType & 0xFF; + } +} \ No newline at end of file Added: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/Session.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/Session.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/Session.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -0,0 +1,364 @@ +/* SessionImpl.java -- concrete definition of SSLSession. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.net.ssl; + +import java.io.Serializable; + +import java.security.Principal; +import java.security.SecureRandom; +import java.security.cert.Certificate; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Set; + +import javax.crypto.SealedObject; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSessionBindingEvent; +import javax.net.ssl.SSLSessionBindingListener; +import javax.net.ssl.SSLSessionContext; +import javax.security.cert.X509Certificate; + +/** + * A concrete implementation of the {@link SSLSession} interface. This + * class is provided to allow pluggable {@link AbstractSessionContext} + * implementations. + */ +public abstract class Session implements SSLSession, Serializable +{ + protected final long creationTime; + protected long lastAccessedTime; + protected int applicationBufferSize; + + protected ID sessionId; + protected Certificate[] localCerts; + protected Certificate[] peerCerts; + protected X509Certificate[] peerCertChain; + protected String peerHost; + protected int peerPort; + protected boolean peerVerified; + protected HashMap<String,Object> values; + protected boolean valid; + protected boolean truncatedMac = false; + transient protected SecureRandom random; + transient protected SSLSessionContext context; + + protected Session() + { + creationTime = System.currentTimeMillis(); + values = new HashMap<String, Object>(); + applicationBufferSize = (1 << 14); + } + + public void access() + { + lastAccessedTime = System.currentTimeMillis (); + } + + public int getApplicationBufferSize() + { + return applicationBufferSize; + } + + public String getCipherSuite() + { + return null; + } + + public long getCreationTime() + { + return creationTime; + } + + public byte[] getId() + { + return sessionId.id(); + } + + public ID id() + { + return sessionId; + } + + public long getLastAccessedTime() + { + return lastAccessedTime; + } + + public Certificate[] getLocalCertificates() + { + if (localCerts == null) + return null; + return (Certificate[]) localCerts.clone(); + } + + public Principal getLocalPrincipal() + { + if (localCerts != null) + { + if (localCerts[0] instanceof java.security.cert.X509Certificate) + return ((java.security.cert.X509Certificate) localCerts[0]).getSubjectDN(); + } + return null; + } + + public int getPacketBufferSize() + { + return applicationBufferSize + 2048; + } + + public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException + { + if (!peerVerified) + throw new SSLPeerUnverifiedException("peer not verified"); + if (peerCerts == null) + return null; + return (Certificate[]) peerCerts.clone(); + } + + public X509Certificate[] getPeerCertificateChain() + throws SSLPeerUnverifiedException + { + if (!peerVerified) + throw new SSLPeerUnverifiedException("peer not verified"); + if (peerCertChain == null) + return null; + return (X509Certificate[]) peerCertChain.clone(); + } + + public String getPeerHost() + { + return peerHost; + } + + public int getPeerPort() + { + return peerPort; + } + + public Principal getPeerPrincipal() throws SSLPeerUnverifiedException + { + if (!peerVerified) + throw new SSLPeerUnverifiedException("peer not verified"); + if (peerCertChain == null) + return null; + return peerCertChain[0].getSubjectDN(); + } + + public SSLSessionContext getSessionContext() + { + return context; + } + + public String[] getValueNames() + { + Set<String> keys = this.values.keySet(); + return keys.toArray(new String[keys.size()]); + } + + public Object getValue(String name) + { + return values.get(name); + } + + public void invalidate() + { + valid = false; + } + + public boolean isValid() + { + return valid; + } + + public void putValue(String name, Object value) + { + values.put(name, value); + try + { + if (value instanceof SSLSessionBindingListener) + ((SSLSessionBindingListener) value).valueBound + (new SSLSessionBindingEvent(this, name)); + } + catch (Exception x) + { + } + } + + public void removeValue(String name) + { + Object value = values.remove(name); + try + { + if (value instanceof SSLSessionBindingListener) + ((SSLSessionBindingListener) value).valueUnbound + (new SSLSessionBindingEvent(this, name)); + } + catch (Exception x) + { + } + } + + public final boolean isTruncatedMac() + { + return truncatedMac; + } + + /** + * Prepare this session for serialization. Private data will be encrypted + * with the given password, and this object will then be ready to be + * serialized. + * + * @param password The password to protect this session with. + * @throws SSLException If encrypting this session's private data fails. + */ + public abstract void prepare (char[] password) throws SSLException; + + /** + * Repair this session's private data after deserialization. This method + * will decrypt this session's private data, and prepare the session for + * use in new SSL connections. + * + * @param password The password to decrypt the private data with. + * @throws SSLException + */ + public abstract void repair(char[] password) throws SSLException; + + /** + * Get the private data of this session. This method may only be called + * after first calling {@link #prepare(char[])}. + * + * @return The sealed private data. + * @throws SSLException If the private data have not been sealed. + */ + public abstract SealedObject privateData() throws SSLException; + + /** + * Set the private data of this session. + * @param data + * @throws SSLException + */ + public abstract void setPrivateData(SealedObject data) throws SSLException; + + // Inner classes. + // ------------------------------------------------------------------------- + + /** + * An SSL or TLS session ID. + */ + public static final class ID implements Comparable, Serializable + { + + // Fields. + // ----------------------------------------------------------------------- + + static final long serialVersionUID = 7887036954666565936L; + /** The ID itself. */ + private final byte[] id; + + // Constructor. + // ----------------------------------------------------------------------- + + /** + * Creates a new ID. + * + * @param id The ID. The array is cloned. + */ + public ID (final byte[] id) + { + if (id.length > 32) + throw new IllegalArgumentException ("session ID's are limited to 32 bytes"); + this.id = (byte[]) id.clone(); + } + + // Instance methods. + // ----------------------------------------------------------------------- + + public byte[] id() + { + return (byte[]) id.clone(); + } + + public boolean equals(Object other) + { + if (!(other instanceof ID)) + return false; + return Arrays.equals(id, ((ID) other).id); + } + + public int hashCode() + { + int code = 0; + for (int i = 0; i < id.length; i++) + code |= (id[i] & 0xFF) << ((i & 3) << 3); + return code; + } + + public int compareTo(Object other) + { + byte[] id2 = ((ID) other).id; + if (id.length != id2.length) + return (id.length < id2.length) ? -1 : 1; + for (int i = 0; i < id.length; i++) + { + if ((id[i] & 0xFF) < (id2[i] & 0xFF)) + return -1; + if ((id[i] & 0xFF) > (id2[i] & 0xFF)) + return 1; + } + return 0; + } + + public String toString() + { + StringBuffer str = new StringBuffer (3 * id.length + 1); + for (int i = 0; i < id.length; i++) + { + int x = id[i] & 0xFF; + str.append (Character.forDigit ((x >>> 4) & 0xF, 16)); + str.append (Character.forDigit (x & 0xF, 16)); + if (i != id.length - 1) + str.append (':'); + } + return str.toString (); + } + } +} \ No newline at end of file Added: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SessionStoreException.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SessionStoreException.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/SessionStoreException.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -0,0 +1,59 @@ +/* SessionStoreException.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.net.ssl; + +import javax.net.ssl.SSLException; + +public class SessionStoreException extends SSLException +{ + public SessionStoreException (final String message) + { + super (message); + } + + public SessionStoreException (final String message, final Throwable cause) + { + super (message, cause); + } + + public SessionStoreException (final Throwable cause) + { + super (cause); + } +} Added: trunk/core/src/classpath/gnu/gnu/javax/security/auth/callback/CertificateCallback.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/security/auth/callback/CertificateCallback.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/security/auth/callback/CertificateCallback.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -0,0 +1,64 @@ +/* CertificateCallback.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.security.auth.callback; + +import java.security.cert.Certificate; + +import javax.security.auth.callback.ConfirmationCallback; + +/** + * A {@link javax.security.auth.callback.Callback} for confirming whether or + * not a certificate may be used. This works similarly to + * {@link ConfirmationCallback}, but additionally contains the certificate + * being verified. Thus, handlers may present the certificate to the user, when + * handling this callback. + * + * @author Casey Marshall (cs...@gn...) + */ +public class CertificateCallback extends ConfirmationCallback +{ + static final long serialVersionUID = 8343869651419225634L; + public final Certificate certificate; + + public CertificateCallback(Certificate cert, String prompt) + { + super(prompt, ERROR, YES_NO_OPTION, NO); + this.certificate = cert; + } +} Added: trunk/core/src/classpath/gnu/gnu/javax/swing/text/html/CharacterAttributeTranslator.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/swing/text/html/CharacterAttributeTranslator.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/swing/text/html/CharacterAttributeTranslator.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -0,0 +1,192 @@ +/* CharacterAttributeTranslator.java -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.swing.text.html; + +import java.awt.Color; +import java.util.HashMap; +import java.util.StringTokenizer; + +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.html.HTML.Attribute; +import javax.swing.text.html.HTML.Tag; + +/** + * This is a small utility class to translate HTML character attributes to + * Swing StyleConstants + */ +public class CharacterAttributeTranslator +{ + /** + * Maps color name to its hex encoding. + */ + private static final HashMap colorMap = new HashMap(); + static + { + colorMap.put("aqua" , "#00FFFF"); + colorMap.put("blue" , "#0000FF"); + colorMap.put("black", "#000000"); + colorMap.put("fuchsia" , "#FF00FF"); + colorMap.put("gray" , "#808080"); + colorMap.put("green" , "#008000"); + colorMap.put("lime" , "#00FF00"); + colorMap.put("maroon" , "#800000"); + colorMap.put("navy" , "#000080"); + colorMap.put("olive" , "#808000"); + colorMap.put("purple" , "#800080"); + colorMap.put("red" , "#FF0000"); + colorMap.put("silver" , "#C0C0C0"); + colorMap.put("teal" , "#008080"); + colorMap.put("white" , "#FFFFFF"); + colorMap.put("yellow" , "#FFFF00"); + } + + /** + * Convert the color string represenation into java.awt.Color. The valid + * values are like "aqua" , "#00FFFF" or "rgb(1,6,44)". + * + * @param colorName the color to convert. + * @return the matching java.awt.color + */ + public static Color getColor(String colorName) + { + colorName = colorName.toLowerCase(); + try + { + if (colorName.startsWith("rgb")) + { + // rgb(red, green, blue) notation. + StringTokenizer st = new StringTokenizer(colorName, " ,()"); + String representation = st.nextToken(); + + // Return null if the representation is not supported. + if (! representation.equals("rgb")) + return null; + int red = Integer.parseInt(st.nextToken()); + int green = Integer.parseInt(st.nextToken()); + int blue = Integer.parseInt(st.nextToken()); + + return new Color(red, green, blue); + } + else + { + String s2 = (String) colorMap.get(colorName); + if (s2 == null) + s2 = colorName; + return Color.decode(s2); + } + } + catch (Exception nex) + { + // Can be either number format exception or illegal argument + // exception. + return null; + } + } + + /** + * Translate the HTML character attribute to the Swing style constant. + * + * @param charAttr the character attributes of the html tag + * @param t the html tag itself + * @param a the attribute set where the translated attributes will be stored + * + * @return true if some attributes were translated, false otherwise. + */ + public static boolean translateTag(MutableAttributeSet charAttr, + Tag t, MutableAttributeSet a) + { + if(t == Tag.FONT) + { + Object color = a.getAttribute(Attribute.COLOR); + if(color != null) + { + Color c = getColor(color.toString()); + if( c == null ) + return false; + charAttr.addAttribute(StyleConstants.Foreground, c); + return true; + } + + if(a.getAttribute(Attribute.SIZE) != null) + { + // FIXME + // charAttr.addAttribute(StyleConstants.FontSize, + // new java.lang.Integer(72)); + return true; + } + } + + if( t == Tag.B ) + { + charAttr.addAttribute(StyleConstants.Bold, Boolean.TRUE); + return true; + } + + if( t == Tag.I ) + { + charAttr.addAttribute(StyleConstants.Italic, Boolean.TRUE); + return true; + } + + if( t == Tag.U ) + { + charAttr.addAttribute(StyleConstants.Underline, Boolean.TRUE); + return true; + } + + if( t == Tag.STRIKE ) + { + charAttr.addAttribute(StyleConstants.StrikeThrough, Boolean.TRUE); + return true; + } + + if( t == Tag.SUP ) + { + charAttr.addAttribute(StyleConstants.Superscript, Boolean.TRUE); + return true; + } + + if( t == Tag.SUB ) + { + charAttr.addAttribute(StyleConstants.Subscript, Boolean.TRUE); + return true; + } + return false; + } +} Deleted: trunk/core/src/classpath/gnu/gnu/javax/swing/text/html/parser/HTML_401Swing.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/swing/text/html/parser/HTML_401Swing.java 2007-01-07 12:50:40 UTC (rev 3020) +++ trunk/core/src/classpath/gnu/gnu/javax/swing/text/html/parser/HTML_401Swing.java 2007-01-07 12:51:25 UTC (rev 3021) @@ -1,91 +0,0 @@ -/* HTML_401Swing.java -- The HTML 4.01 DTD, adapted for HTML rendering in Swing - Copyright (C) 2006 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.javax.swing.text.html.parser; - -import javax.swing.text.html.parser.DTD; - -/** - * This class is necessary because the current implementation of the GNU - * Classpath Swing requires always enclose the text into paragraphs. - * - * @author Audrius Meskauskas (Aud...@Bi...) - */ -public class HTML_401Swing extends HTML_401F -{ - /** - * The singleton instance; - */ - final static HTML_401Swing singleton = new HTML_401Swing(); - - /** - * Either takes the document (by name) from DTD table, or - * creates a new instance and registers it in the tabe. - * The document is registerd under name "-//W3C//DTD HTML 4.01 Frameset//EN". - * @return The new or existing DTD for parsing HTML 4.01 Frameset. - */ - public static DTD getInstance() - { - return singleton; - } - - /** - * Get elements that are allowed in the document body, at the zero level. - * This list disallows the text at this level (the implied P tag will be - * generated). It also disallows A, B, I, U, CITE and other similar - * elements that have the plain text inside. They will also be placed - * inside the generated implied P tags. - */ - protected String[] getBodyElements() - { - return new String[] { - APPLET, BASEFONT, - BR, BUTTON, - IFRAME, IMG, - INPUT, LABEL, MAP, OBJECT, - SCRIPT, SELECT, - TEXTAREA, - BLOCKQUOTE, CENTER, DEL, DIR, - DIV, DL, FIELDSET, FORM, H1, - H2, H3, H4, H5, H6,... [truncated message content] |
From: <ls...@us...> - 2007-01-07 12:50:41
|
Revision: 3020 http://jnode.svn.sourceforge.net/jnode/?rev=3020&view=rev Author: lsantha Date: 2007-01-07 04:50:40 -0800 (Sun, 07 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Extension.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Finished.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Handshake.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Jessie.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ProtocolVersion.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Random.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerHello.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerKeyExchange.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Signature.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Util.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/X509KeyManagerFactory.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/X509TrustManagerFactory.java Added Paths: ----------- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ExchangeKeys.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ExtensionList.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/HelloRequest.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/InputSecurityParameters.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/KeyExchangeAlgorithm.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/MacAlgorithm.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/MaxFragmentLength.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/OutputSecurityParameters.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/PreSharedKeyManagerFactoryImpl.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Record.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLContextImpl.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLEngineImpl.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLRSASignatureImpl.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLServerSocketFactoryImpl.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLServerSocketImpl.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLSocketFactoryImpl.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLSocketImpl.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLv3HMacMD5Impl.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLv3HMacSHAImpl.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerDHParams.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerHandshake.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerHelloBuilder.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerHelloDone.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerKeyExchangeBuilder.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerKeyExchangeParams.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerNameList.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerPSKParameters.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerRSAParams.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ServerRSA_PSKParameters.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SessionImpl.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SignatureAlgorithm.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SimpleSessionContext.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/TruncatedHMAC.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/TrustedAuthorities.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/UnresolvedExtensionValue.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/X500PrincipalList.java Removed Paths: ------------- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Context.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/DigestInputStream.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/DigestOutputStream.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Enumerated.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Extensions.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/GNUSecurityParameters.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/JCESecurityParameters.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/JessieDHPrivateKey.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/JessieDHPublicKey.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/KeyPool.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/OverflowException.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/RecordInput.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/RecordInputStream.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/RecordOutputStream.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/RecordingInputStream.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLRSASignature.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLServerSocket.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLServerSocketFactory.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLSocket.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLSocketFactory.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLSocketInputStream.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SSLSocketOutputStream.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SecurityParameters.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Session.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SessionContext.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/SynchronizedRandom.java trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/XMLSessionContext.java Deleted: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Context.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Context.java 2007-01-07 12:48:35 UTC (rev 3019) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Context.java 2007-01-07 12:50:40 UTC (rev 3020) @@ -1,330 +0,0 @@ -/* Context.java -- SSLContext implementation. - Copyright (C) 2006 Free Software Foundation, Inc. - -This file is a part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or (at -your option) any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 -USA - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.javax.net.ssl.provider; - - -import java.security.InvalidAlgorithmParameterException; -import java.security.KeyStoreException; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.SecureRandom; -import java.security.UnrecoverableKeyException; - -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContextSpi; -import javax.net.ssl.SSLSessionContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509KeyManager; -import javax.net.ssl.X509TrustManager; - -import gnu.javax.net.ssl.NullManagerParameters; -import gnu.javax.net.ssl.SRPTrustManager; -import gnu.javax.net.ssl.StaticTrustAnchors; - -/** - * This is Jessie's implementation of a {@link javax.net.ssl.SSLContext} - * engine, and is available under the algorithm names ``SSLv3'', ``SSL'', - * ``TLSv1'', and ``TLS''. - */ -public final class Context extends SSLContextSpi -{ - - // Fields. - // ------------------------------------------------------------------------- - - private SessionContext clientSessions; - private SessionContext serverSessions; - private X509KeyManager keyManager; - private X509TrustManager trustManager; - private SRPTrustManager srpTrustManager; - private SecureRandom random; - - // Constructor. - // ------------------------------------------------------------------------- - - public Context() - { - String codec = Util.getSecurityProperty("jessie.clientSessionContext.codec"); - String codecClass = null; - if (codec == null) - { - codec = "null"; - } - if (codec.equalsIgnoreCase("xml")) - { - codecClass = "gnu.javax.net.ssl.provider.XMLSessionContext"; - } - else if (codec.equalsIgnoreCase("jdbc")) - { - codecClass = "gnu.javax.net.ssl.provider.JDBCSessionContext"; - } - else if (codec.equalsIgnoreCase("null")) - { - codecClass = "gnu.javax.net.ssl.provider.SessionContext"; - } - else - { - throw new IllegalArgumentException("no such codec: " + codec); - } - try - { - ClassLoader cl = Context.class.getClassLoader(); - if (cl == null) - { - cl = ClassLoader.getSystemClassLoader(); - } - clientSessions = (SessionContext) cl.loadClass(codecClass).newInstance(); - } - catch (Exception ex) - { - ex.printStackTrace(); - throw new IllegalArgumentException(ex.toString()); - } - - codec = Util.getSecurityProperty("jessie.serverSessionContext.codec"); - if (codec == null) - { - codec = "null"; - } - if (codec.equalsIgnoreCase("xml")) - { - codecClass = "gnu.javax.net.ssl.provider.XMLSessionContext"; - } - else if (codec.equalsIgnoreCase("jdbc")) - { - codecClass = "gnu.javax.net.ssl.provider.JDBCSessionContext"; - } - else if (codec.equalsIgnoreCase("null")) - { - codecClass = "gnu.javax.net.ssl.provider.SessionContext"; - } - else - { - throw new IllegalArgumentException("no such codec: " + codec); - } - try - { - ClassLoader cl = Context.class.getClassLoader(); - if (cl == null) - { - cl = ClassLoader.getSystemClassLoader(); - } - serverSessions = (SessionContext) cl.loadClass(codecClass).newInstance(); - } - catch (Exception ex) - { - ex.printStackTrace(); - throw new IllegalArgumentException(ex.toString()); - } - } - - // Engine methods. - // ------------------------------------------------------------------------- - - protected SSLSessionContext engineGetClientSessionContext() - { - return clientSessions; - } - - protected SSLSessionContext engineGetServerSessionContext() - { - return serverSessions; - } - - protected javax.net.ssl.SSLServerSocketFactory engineGetServerSocketFactory() - { - if (keyManager == null || (trustManager == null && srpTrustManager == null) - || random == null) - { - throw new IllegalStateException(); - } - return new SSLServerSocketFactory(trustManager, srpTrustManager, keyManager, - random, serverSessions); - } - - protected javax.net.ssl.SSLSocketFactory engineGetSocketFactory() - { - if (keyManager == null || trustManager == null || random == null) - { - throw new IllegalStateException(); - } - return new SSLSocketFactory(trustManager, keyManager, random, clientSessions); - } - - protected void engineInit(KeyManager[] keyManagers, - TrustManager[] trustManagers, SecureRandom random) - throws KeyManagementException - { - keyManager = null; - trustManager = null; - srpTrustManager = null; - if (keyManagers != null) - { - for (int i = 0; i < keyManagers.length; i++) - { - if (keyManagers[i] instanceof X509KeyManager) - { - keyManager = (X509KeyManager) keyManagers[i]; - break; - } - } - } - if (keyManager == null) - { - keyManager = defaultKeyManager(); - } - if (trustManagers != null) - { - for (int i = 0; i < trustManagers.length; i++) - { - if (trustManagers[i] instanceof X509TrustManager) - { - if (trustManager == null) - { - trustManager = (X509TrustManager) trustManagers[i]; - } - } - else if (trustManagers[i] instanceof SRPTrustManager) - { - if (srpTrustManager == null) - { - srpTrustManager = (SRPTrustManager) trustManagers[i]; - } - } - } - } - if (trustManager == null && srpTrustManager == null) - { - trustManager = defaultTrustManager(); - } - if (random != null) - { - this.random = random; - } - else - { - this.random = defaultRandom(); - } - } - - // Own methods. - // ------------------------------------------------------------------------- - - private X509KeyManager defaultKeyManager() throws KeyManagementException - { - KeyManagerFactory fact = null; - try - { - fact = KeyManagerFactory.getInstance("JessieX509", "Jessie"); - } - catch (NoSuchAlgorithmException nsae) - { - throw new KeyManagementException(); - } - catch (NoSuchProviderException nspe) - { - throw new KeyManagementException(); - } - try - { - fact.init(null, null); - return (X509KeyManager) fact.getKeyManagers()[0]; - } - catch (NoSuchAlgorithmException nsae) { } - catch (KeyStoreException kse) { } - catch (UnrecoverableKeyException uke) { } - catch (IllegalStateException ise) { } - - try - { - fact.init(new NullManagerParameters()); - return (X509KeyManager) fact.getKeyManagers()[0]; - } - catch (Exception shouldNotHappen) - { - throw new Error(shouldNotHappen.toString()); - } - } - - private X509TrustManager defaultTrustManager() throws KeyManagementException - { - try - { - TrustManagerFactory fact = - TrustManagerFactory.getInstance("JessieX509", "Jessie"); - fact.init(StaticTrustAnchors.CA_CERTS); - return (X509TrustManager) fact.getTrustManagers()[0]; - } - catch (NoSuchAlgorithmException nsae) - { - throw new KeyManagementException(nsae.toString()); - } - catch (NoSuchProviderException nspe) - { - throw new KeyManagementException(nspe.toString()); - } - catch (InvalidAlgorithmParameterException kse) - { - throw new KeyManagementException(kse.toString()); - } - } - - private SecureRandom defaultRandom() throws KeyManagementException - { - String alg = Util.getSecurityProperty("jessie.secure.random"); - if (alg == null) - { - alg = "Fortuna"; - } - SecureRandom rand = null; - try - { - rand = SecureRandom.getInstance(alg); - } - catch (NoSuchAlgorithmException nsae) - { - throw new KeyManagementException(nsae.toString()); - } - - return rand; - } -} Deleted: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/DigestInputStream.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/DigestInputStream.java 2007-01-07 12:48:35 UTC (rev 3019) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/DigestInputStream.java 2007-01-07 12:50:40 UTC (rev 3020) @@ -1,103 +0,0 @@ -/* DigestInputStream.java -- digesting input stream. - Copyright (C) 2006 Free Software Foundation, Inc. - -This file is a part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or (at -your option) any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 -USA - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.javax.net.ssl.provider; - -import java.io.FilterInputStream; -import java.io.InputStream; -import java.io.IOException; - -import gnu.java.security.hash.IMessageDigest; - -final class DigestInputStream extends FilterInputStream -{ - - // Fields. - // ------------------------------------------------------------------------- - - private IMessageDigest md5, sha; - private boolean digesting; - - // Constructor. - // ------------------------------------------------------------------------- - - DigestInputStream(InputStream in, IMessageDigest md5, IMessageDigest sha) - { - super(in); - if (md5 == null || sha == null) - throw new NullPointerException(); - this.md5 = md5; - this.sha = sha; - digesting = true; - } - - // Instance methods. - // ------------------------------------------------------------------------- - - void setDigesting(boolean digesting) - { - this.digesting = digesting; - } - - public int read() throws IOException - { - int i = in.read(); - if (digesting && i != -1) - { - md5.update((byte) i); - sha.update((byte) i); - } - return i; - } - - public int read(byte[] buf) throws IOException - { - return read(buf, 0, buf.length); - } - - public int read(byte[] buf, int off, int len) throws IOException - { - int ret = in.read(buf, off, len); - if (digesting && ret != -1) - { - md5.update(buf, off, ret); - sha.update(buf, off, ret); - } - return ret; - } -} Deleted: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/DigestOutputStream.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/DigestOutputStream.java 2007-01-07 12:48:35 UTC (rev 3019) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/DigestOutputStream.java 2007-01-07 12:50:40 UTC (rev 3020) @@ -1,107 +0,0 @@ -/* DigestOutputStream.java -- digesting output stream. - Copyright (C) 2006 Free Software Foundation, Inc. - -This file is a part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or (at -your option) any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 -USA - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.javax.net.ssl.provider; - -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -import gnu.java.security.hash.IMessageDigest; - -final class DigestOutputStream extends FilterOutputStream -{ - - // Fields. - // ------------------------------------------------------------------------- - - private IMessageDigest md5, sha; - private boolean digesting; - - // Constructor. - // ------------------------------------------------------------------------- - - DigestOutputStream(OutputStream out, IMessageDigest md5, IMessageDigest sha) - { - super(out); - this.md5 = md5; - this.sha = sha; - digesting = true; - } - - // Instance methods. - // ------------------------------------------------------------------------- - - void setDigesting(boolean digesting) - { - this.digesting = digesting; - } - - public void write(int b) throws IOException - { - if (digesting) - { - md5.update((byte) b); - sha.update((byte) b); - } - out.write(b); - } - - public void write(byte[] buf) throws IOException - { - write(buf, 0, buf.length); - } - - public void write(byte[] buf, int off, int len) throws IOException - { - if (buf == null) - { - throw new NullPointerException(); - } - if (off < 0 || len < 0 || off+len > buf.length) - { - throw new ArrayIndexOutOfBoundsException(); - } - if (digesting) - { - md5.update(buf, off, len); - sha.update(buf, off, len); - } - out.write(buf, off, len); - } -} Deleted: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Enumerated.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Enumerated.java 2007-01-07 12:48:35 UTC (rev 3019) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Enumerated.java 2007-01-07 12:50:40 UTC (rev 3020) @@ -1,79 +0,0 @@ -/* Enumerated.java -- Interface to enumerated types. - Copyright (C) 2006 Free Software Foundation, Inc. - -This file is a part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or (at -your option) any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 -USA - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.javax.net.ssl.provider; - -/** - * An enumerated type in the SSL protocols. Enumerated values take on - * one of a set of possible numeric values, which are not specifically - * ordered, and may be extensible to a maximum value. - * - * <pre>enum { e1(v1), e2(v2), ... [[, (n) ]] }</pre> - * - * <p>Enumerated types are encoded as big-endian multibyte integers, - * which take up the least possible number of bytes. Thus, an - * enumeration with up to 255 values will be encoded in a single byte, - * and so on. - * - * @author Casey Marshall (rs...@me...) - */ -interface Enumerated -{ - - /** - * Returns the encoded value of this enumerated value, which is - * appropriate to send over-the-wire. - * - * @return The encoded value. - */ - byte[] getEncoded(); - - /** - * Returns the numeric value of this enumerated value. - * - * @return The numeric value. - */ - int getValue(); - - /** - * Returns a string representation of this enumerated value. - * - * @return The string. - */ - String toString(); -} Added: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ExchangeKeys.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ExchangeKeys.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ExchangeKeys.java 2007-01-07 12:50:40 UTC (rev 3020) @@ -0,0 +1,54 @@ +/* ExchangeKeys.java -- key exchange values. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.net.ssl.provider; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public abstract class ExchangeKeys implements Constructed +{ + + protected ByteBuffer buffer; + + public ExchangeKeys (final ByteBuffer buffer) + { + if (buffer != null) + this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN); + } +} \ No newline at end of file Modified: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Extension.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Extension.java 2007-01-07 12:48:35 UTC (rev 3019) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Extension.java 2007-01-07 12:50:40 UTC (rev 3020) @@ -38,136 +38,190 @@ package gnu.javax.net.ssl.provider; -import java.io.EOFException; -import java.io.InputStream; -import java.io.IOException; -import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; -final class Extension implements Constructed +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * An SSL hello extension. + * + * <pre> + * struct { + * ExtensionType extension_type; + * opaque extension_data<0..2^16-1>; + * } Extension;</pre> + * + * @author cs...@gn... + */ +public final class Extension implements Builder, Constructed { // Fields. // ------------------------------------------------------------------------- - private final Type type; - private final byte[] value; + private ByteBuffer buffer; // Constructor. // ------------------------------------------------------------------------- - Extension(Type type, byte[] value) - { - if (type == null || value == null) + public Extension(final ByteBuffer buffer) { - throw new NullPointerException(); + this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN); } - this.type = type; - this.value = value; + + public Extension(final Type type, final Value value) + { + ByteBuffer valueBuffer = value.buffer(); + int length = 2 + 2 + valueBuffer.remaining(); + buffer = ByteBuffer.allocate(length); + buffer.putShort((short) type.getValue()); + buffer.putShort((short) valueBuffer.remaining()); + buffer.put(valueBuffer); + buffer.rewind(); } - // Class method. + // Instance methods. // ------------------------------------------------------------------------- - static Extension read(InputStream in) throws IOException + public int length () { - Type t = Type.read(in); - int len = (in.read() & 0xFF) << 8 | (in.read() & 0xFF); - byte[] v = new byte[len]; - int count = 0; - while (count < len) + return (buffer.getShort (2) & 0xFFFF) + 4; + } + + public ByteBuffer buffer() { - int l = in.read(v, count, len - count); - if (l == -1) + return (ByteBuffer) buffer.duplicate().limit(length()); + } + + public Type type() { - throw new EOFException("unexpected end of extension"); + return Type.forValue (buffer.getShort (0) & 0xFFFF); } - count += l; + + public byte[] valueBytes() + { + int len = buffer.getShort (2) & 0xFFFF; + byte[] value = new byte[len]; + ((ByteBuffer) buffer.duplicate ().position (4)).get (value); + return value; } - return new Extension(t, v); + + public ByteBuffer valueBuffer() + { + int len = buffer.getShort(2) & 0xFFFF; + return ((ByteBuffer) buffer.duplicate().position(4).limit(len+4)).slice(); } - // Instance methods. - // ------------------------------------------------------------------------- + public Value value() + { + switch (type ()) + { + case SERVER_NAME: + return new ServerNameList(valueBuffer()); - public void write(OutputStream out) throws IOException + case MAX_FRAGMENT_LENGTH: + switch (valueBuffer().get() & 0xFF) { - out.write(type.getEncoded()); - out.write(value.length >>> 8 & 0xFF); - out.write(value.length & 0xFF); - out.write(value); + case 1: return MaxFragmentLength.LEN_2_9; + case 2: return MaxFragmentLength.LEN_2_10; + case 3: return MaxFragmentLength.LEN_2_11; + case 4: return MaxFragmentLength.LEN_2_12; + default: + throw new IllegalArgumentException("invalid max_fragment_len"); + } + + case TRUNCATED_HMAC: + return new TruncatedHMAC(); + + case CLIENT_CERTIFICATE_URL: + return new CertificateURL(valueBuffer()); + + case TRUSTED_CA_KEYS: + return new TrustedAuthorities(valueBuffer()); + + case STATUS_REQUEST: + return new CertificateStatusRequest(valueBuffer()); + + case SRP: + case CERT_TYPE: + } + return new UnresolvedExtensionValue(valueBuffer()); } - Type getType() + public void setLength (final int newLength) { - return type; + if (newLength < 0 || newLength > 65535) + throw new IllegalArgumentException ("length is out of bounds"); + buffer.putShort (2, (short) newLength); } - byte[] getValue() + public void setType (final Type type) { - return value; + buffer.putShort(0, (short) type.getValue()); } + public void setValue (byte[] value) + { + setValue (value, 0, value.length); + } + + public void setValue (final byte[] value, final int offset, final int length) + { + if (length != length ()) + throw new IllegalArgumentException ("length is different than claimed length"); + ((ByteBuffer) buffer.duplicate().position(4)).put(value, offset, length); + } + public String toString() { + return toString(null); + } + + public String toString(String prefix) + { StringWriter str = new StringWriter(); PrintWriter out = new PrintWriter(str); + if (prefix != null) out.print (prefix); out.println("struct {"); - out.println(" type = " + type + ";"); + if (prefix != null) out.print (prefix); + out.println(" type = " + type () + ";"); + if (prefix != null) out.print (prefix); + String subprefix = " "; + if (prefix != null) subprefix = prefix + subprefix; out.println(" value ="); - out.println(Util.hexDump(value, " ")); - out.println("} Extension;"); + out.println(value().toString(subprefix)); + if (prefix != null) out.print (prefix); + out.print("} Extension;"); return str.toString(); } - // Inner class. + // Inner classes. // ------------------------------------------------------------------------- - static final class Type implements Enumerated + public static enum Type { + SERVER_NAME (0), + MAX_FRAGMENT_LENGTH (1), + CLIENT_CERTIFICATE_URL (2), + TRUSTED_CA_KEYS (3), + TRUNCATED_HMAC (4), + STATUS_REQUEST (5), + SRP (6), + CERT_TYPE (7); - // Constants and fields. - // ----------------------------------------------------------------------- - - static final Type SERVER_NAME = new Type(0); - static final Type MAX_FRAGMENT_LENGTH = new Type(1); - static final Type CLIENT_CERTIFICATE_URL = new Type(2); - static final Type TRUSTED_CA_KEYS = new Type(3); - static final Type TRUNCATED_HMAC = new Type(4); - static final Type STATUS_REQUEST = new Type(5); - static final Type SRP = new Type(6); - static final Type CERT_TYPE = new Type(7); - private final int value; - // Constructor. - // ----------------------------------------------------------------------- - private Type(int value) { this.value = value; } - // Class methods. - // ----------------------------------------------------------------------- - - static Type read(InputStream in) throws IOException + public static Type forValue (final int value) { - int i = in.read(); - if (i == -1) + switch (value & 0xFFFF) { - throw new EOFException("unexpected end of input stream"); - } - int value = (i & 0xFF) << 8; - i = in.read(); - if (i == -1) - { - throw new EOFException("unexpected end of input stream"); - } - value |= i & 0xFF; - switch (value) - { case 0: return SERVER_NAME; case 1: return MAX_FRAGMENT_LENGTH; case 2: return CLIENT_CERTIFICATE_URL; @@ -176,39 +230,17 @@ case 5: return STATUS_REQUEST; case 6: return SRP; case 7: return CERT_TYPE; - default: return new Type(value); + default: return null; } } - // Instance methods. - // ----------------------------------------------------------------------- - - public byte[] getEncoded() - { - return new byte[] { - (byte) (value >>> 8 & 0xFF), (byte) (value & 0xFF) - }; - } - public int getValue() { return value; } + } - public String toString() + public static abstract class Value implements Builder, Constructed { - switch (value) - { - case 0: return "server_name"; - case 1: return "max_fragment_length"; - case 2: return "client_certificate_url"; - case 3: return "trusted_ca_keys"; - case 4: return "truncated_hmac"; - case 5: return "status_request"; - case 6: return "srp"; - case 7: return "cert_type"; - default: return "unknown(" + value + ")"; - } - } } } Added: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ExtensionList.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ExtensionList.java (rev 0) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/ExtensionList.java 2007-01-07 12:50:40 UTC (rev 3020) @@ -0,0 +1,290 @@ +package gnu.javax.net.ssl.provider; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; + +/** + * A list of extensions, that may appear in either the {@link ClientHello} or + * {@link ServerHello}. The form of the extensions list is: + * + * <tt> Extension extensions_list<1..2^16-1></tt> + * + * @author csm + */ +public class ExtensionList implements Builder, Iterable<Extension> +{ + private final ByteBuffer buffer; + private int modCount; + + public ExtensionList (ByteBuffer buffer) + { + this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN); + modCount = 0; + } + + public ExtensionList(List<Extension> extensions) + { + int length = 2; + for (Extension extension : extensions) + length += extension.length(); + buffer = ByteBuffer.allocate(length); + buffer.putShort((short) (length - 2)); + for (Extension extension : extensions) + buffer.put(extension.buffer()); + buffer.rewind(); + } + + public ByteBuffer buffer() + { + return (ByteBuffer) buffer.duplicate().limit(length()); + } + + public Extension get (final int index) + { + int length = length (); + int i; + int n = 0; + for (i = 2; i < length && n < index; ) + { + int l = buffer.getShort (i+2) & 0xFFFF; + i += l + 4; + n++; + } + if (n < index) + throw new IndexOutOfBoundsException ("no elemenet at " + index); + int el = buffer.getShort (i+2) & 0xFFFF; + ByteBuffer b = (ByteBuffer) buffer.duplicate().position(i).limit(i+el+4); + return new Extension(b.slice()); + } + + /** + * Returns the number of extensions this list contains. + * + * @return The number of extensions. + */ + public int size () + { + int length = length (); + if (length == 0) + return 0; + int n = 0; + for (int i = 2; i < length; ) + { + int len = buffer.getShort (i+2) & 0xFFFF; + i += len + 4; + n++; + } + return n; + } + + /** + * Returns the length of this extension list, in bytes. + * + * @return The length of this extension list, in bytes. + */ + public int length () + { + return (buffer.getShort (0) & 0xFFFF) + 2; + } + + /** + * Sets the extension at index <i>i</i> to <i>e</i>. Note that setting an + * element at an index <b>may</b> invalidate any other elements that come + * after element at index <i>i</i>. In other words, no attempt is made to + * move existing elements in this list, and since extensions are variable + * length, you can <em>not</em> guarantee that extensions later in the list + * will still be valid. + * + * <p>Thus, elements of this list <b>must</b> be set in order of increasing + * index. + * + * @param index The index to set the extension at. + * @param e The extension. + * @throws java.nio.BufferOverflowException If setting the extension overflows + * the buffer. + * @throws IllegalArgumentException If it isn't possible to find the given index + * in the current list (say, if no element index - 1 is set), or if setting + * the extension will overflow the current list length (given by {@link + * #length()}). + */ + public void set (final int index, Extension e) + { + int length = length(); + int n = 0; + int i; + for (i = 2; i < length && n < index; ) + { + int len = buffer.getShort(i+2) & 0xFFFF; + i += len + 4; + n++; + } + if (n < index) + throw new IllegalArgumentException("nothing set at index " + (index-1) + + " or insufficient space"); + if (i + e.length() + 2 > length) + throw new IllegalArgumentException("adding this element will exceed the " + + "list length"); + buffer.putShort(i, (short) e.type().getValue()); + buffer.putShort(i+2, (short) e.length()); + ((ByteBuffer) buffer.duplicate().position(i+4)).put (e.valueBuffer()); + modCount++; + } + + /** + * Reserve space for an extension at index <i>i</i> in the list. In other + * words, this does the job of {@link #set(int, Extension)}, but does not + * copy the extension value to the underlying buffer. + * + * @param index The index of the extension to reserve space for. + * @param t The type of the extension. + * @param eLength The number of bytes to reserve for this extension. The total + * number of bytes used by this method is this length, plus four. + */ + public void set (final int index, Extension.Type t, final int eLength) + { + int length = length (); + int n = 0; + int i; + for (i = 2; i < length && n < index; ) + { + int len = buffer.getShort (i+2) & 0xFFFF; + i += len + 4; + n++; + } + if (n < index) + throw new IllegalArgumentException ("nothing set at index " + (index-1) + + " or insufficient space"); + if (i + eLength + 2 > length) + throw new IllegalArgumentException ("adding this element will exceed the " + + "list length"); + buffer.putShort(i, (short) t.getValue()); + buffer.putShort(i+2, (short) eLength); + modCount++; + } + + /** + * Set the total length of this list, in bytes. + * + * @param newLength The new list length. + */ + public void setLength (final int newLength) + { + if (newLength < 0 || newLength > 65535) + throw new IllegalArgumentException ("invalid length"); + buffer.putShort (0, (short) newLength); + modCount++; + } + + public Iterator<Extension> iterator() + { + return new ExtensionsIterator(); + } + + public String toString() + { + return toString (null); + } + + public String toString(final String prefix) + { + StringWriter str = new StringWriter(); + PrintWriter out = new PrintWriter(str); + if (prefix != null) out.print(prefix); + out.println("ExtensionList {"); + if (prefix != null) out.print(prefix); + out.print(" length = "); + out.print(length()); + out.println(";"); + String subprefix = " "; + if (prefix != null) + subprefix = prefix + subprefix; + for (Extension e : this) + out.println(e.toString(subprefix)); + if (prefix != null) out.print(prefix); + out.print("};"); + return str.toString(); + } + + /** + * List iterator interface to an extensions list. + * + * @author cs...@gn... + */ + public final class ExtensionsIterator implements ListIterator<Extension> + { + private final int modCount; + private int index; + private final int size; + + public ExtensionsIterator () + { + this.modCount = ExtensionList.this.modCount; + index = 0; + size = size (); + } + + public boolean hasNext() + { + return index < size; + } + + public boolean hasPrevious() + { + return index > 0; + } + + public Extension next() throws NoSuchElementException + { + if (modCount != ExtensionList.this.modCount) + throw new ConcurrentModificationException (); + if (!hasNext ()) + throw new NoSuchElementException (); + return get (index++); + } + + public Extension previous() throws NoSuchElementException + { + if (modCount != ExtensionList.this.modCount) + throw new ConcurrentModificationException (); + if (!hasPrevious ()) + throw new NoSuchElementException (); + return get (--index); + } + + public int nextIndex() + { + if (hasNext ()) + return index + 1; + return index; + } + + public int previousIndex() + { + if (hasPrevious ()) + return index - 1; + return -1; + } + + public void add(Extension e) + { + throw new UnsupportedOperationException ("cannot add items to this iterator"); + } + + public void remove() + { + throw new UnsupportedOperationException ("cannot remove items from this iterator"); + } + + public void set(Extension e) + { + ExtensionList.this.set (index, e); + } + } +} Deleted: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Extensions.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Extensions.java 2007-01-07 12:48:35 UTC (rev 3019) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Extensions.java 2007-01-07 12:50:40 UTC (rev 3020) @@ -1,159 +0,0 @@ -/* Extensions.java -- various static extension utilities. - Copyright (C) 2006 Free Software Foundation, Inc. - -This file is a part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or (at -your option) any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 -USA - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package gnu.javax.net.ssl.provider; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import javax.security.auth.x500.X500Principal; - -import gnu.java.security.x509.X500DistinguishedName; - -final class Extensions -{ - - // Constants. - // ------------------------------------------------------------------------- - - private static final Integer _512 = new Integer(512), - _1024 = new Integer(1024), _2048 = new Integer(2048), - _4096 = new Integer(4096); - - // Class methods only. - private Extensions() { } - - // Class methods. - // ------------------------------------------------------------------------- - - static List getServerName(Extension ex) - { - LinkedList l = new LinkedList(); - byte[] buf = ex.getValue(); - int pos = 0; - try - { - while (pos < buf.length) - { - if (buf[pos++] != 0) - break; - int len = (buf[pos++] & 0xFF) << 8; - len |= buf[pos++] & 0xFF; - l.add(new String(buf, pos, len, "UTF-8")); - pos += len; - } - } - catch (Exception x) - { - } - return Collections.unmodifiableList(l); - } - - static List getClientCertTypes(Extension ex) throws IOException - { - List l = new LinkedList(); - ByteArrayInputStream in = new ByteArrayInputStream(ex.getValue()); - final int len = in.read() & 0xFF; - for (int i = 0; i < len; i++) - { - l.add(CertificateType.read(in)); - } - return Collections.unmodifiableList(l); - } - - static CertificateType getServerCertType(Extension ex) throws IOException - { - return CertificateType.read(new ByteArrayInputStream(ex.getValue())); - } - - static Integer getMaxFragmentLength(Extension ex) - { - switch (ex.getValue()[0] & 0xFF) - { - case 1: return _512; - case 2: return _1024; - case 3: return _2048; - case 4: return _4096; - } - throw new IllegalArgumentException(); - } - - static Object[] getTrustedCA(Extension ex) - { - byte[] buf = ex.getValue(); - int type = buf[0] & 0xFF; - try - { - switch (type) - { - case 0: - return new Object[] { new Integer(type), null }; - case 1: - case 3: - return new Object[] { new Integer(type), - Util.trim(buf, 1, 20) }; - case 2: - return new Object[] { new Integer(type), - new X500Principal(Util.trim(buf, 1, 20)) }; - } - } - catch (Exception x) - { - } - throw new IllegalArgumentException(); - } - - static String getSRPUsername(Extension ex) - { - int len = ex.getValue()[0] & 0xFF; - if (len > ex.getValue().length - 1) - throw new IllegalArgumentException(); - try - { - return new String(ex.getValue(), 1, len, "UTF-8"); - } - catch (UnsupportedEncodingException uee) - { - throw new Error(uee.toString()); - } - } -} Modified: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Finished.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Finished.java 2007-01-07 12:48:35 UTC (rev 3019) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/Finished.java 2007-01-07 12:50:40 UTC (rev 3020) @@ -38,106 +38,136 @@ package gnu.javax.net.ssl.provider; -import java.io.DataInputStream; -import java.io.InputStream; -import java.io.IOException; -import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.ByteBuffer; + final class Finished implements Handshake.Body { // Fields. // ------------------------------------------------------------------------- - /** TLSv1.x verify data. */ - private final byte[] verifyData; + private final ByteBuffer buffer; + private final ProtocolVersion version; - /** SSLv3 message digest pair. */ - private final byte[] md5, sha; - // Constructor. // ------------------------------------------------------------------------- - Finished(byte[] verifyData) + Finished (final ByteBuffer buffer, final ProtocolVersion version) { - this.verifyData = verifyData; - md5 = sha = null; + buffer.getClass (); + version.getClass (); + this.buffer = buffer; + this.version = version; } - Finished(byte[] md5, byte[] sha) + // Instance methods. + // ------------------------------------------------------------------------- + + public int length () { - this.md5 = md5; - this.sha = sha; - verifyData = null; + if (version.compareTo(ProtocolVersion.TLS_1) >= 0) + return 12; + if (version == ProtocolVersion.SSL_3) + return 36; + throw new IllegalArgumentException ("length for this version unknown"); } - // Class methods. - // ------------------------------------------------------------------------- + byte[] verifyData() + { + if (version.compareTo(ProtocolVersion.TLS_1) >= 0) + { + byte[] verify = new byte[12]; + buffer.position (0); + buffer.get (verify); + return verify; + } + throw new IllegalArgumentException ("not TLSv1.0 or later"); + } - static Finished read(InputStream in, CipherSuite suite) - throws IOException + byte[] md5Hash() { - DataInputStream din = new DataInputStream(in); - if (suite.getVersion().equals(ProtocolVersion.SSL_3)) + if (version == ProtocolVersion.SSL_3) { byte[] md5 = new byte[16]; - byte[] sha = new byte[20]; - din.readFully(md5); - din.readFully(sha); - return new Finished(md5, sha); + buffer.position (0); + buffer.get (md5); + return md5; } - else - { - byte[] buf = new byte[12]; - din.readFully(buf); - return new Finished(buf); - } + throw new IllegalArgumentException ("not SSLv3"); } - // Instance methods. - // ------------------------------------------------------------------------- - - public void write(OutputStream out) throws IOException + byte[] shaHash() { - if (verifyData != null) - out.write(verifyData); - else + if (version == ProtocolVersion.SSL_3) { - out.write(md5); - out.write(sha); + byte[] sha = new byte[20]; + buffer.position (16); + buffer.get (sha); + return sha; } + throw new IllegalArgumentException ("not SSLv3"); } - byte[] getVerifyData() + void setVerifyData (final byte[] verifyData, final int offset) { - return verifyData; + if (version == ProtocolVersion.SSL_3) + throw new IllegalArgumentException ("not TLSv1"); + buffer.position (0); + buffer.put (verifyData, offset, 12); } - byte[] getMD5Hash() + void setMD5Hash (final byte[] md5, final int offset) { - return md5; + if (version != ProtocolVersion.SSL_3) + throw new IllegalArgumentException ("not SSLv3"); + buffer.position (0); + buffer.put (md5, offset, 16); } - byte[] getSHAHash() + void setShaHash (final byte[] sha, final int offset) { - return sha; + if (version != ProtocolVersion.SSL_3) + throw new IllegalArgumentException ("not SSLv3"); + buffer.position (16); + buffer.put (sha, offset, 20); } - public String toString() + public String toString () { - String nl = System.getProperty("line.separator"); - if (verifyData != null) + return toString (null); + } + + public String toString (final String prefix) + { + StringWriter str = new StringWriter (); + PrintWriter out = new PrintWriter (str); + if (prefix != null) + out.print (prefix); + out.println ("struct {"); + if (prefix != null) + out.print (prefix); + if (version.compareTo(ProtocolVersion.TLS_1) >= 0) { - return "struct {" + nl + - " verifyData = " + Util.toHexString(verifyData, ':') + ";" + nl + - "} Finished;" + nl; + out.print (" verifyData = "); + out.print (Util.toHexString (verifyData (), ':')); } - else + else if (version == ProtocolVersion.SSL_3) { - return "struct {" + nl + - " md5Hash = " + Util.toHexString(md5, ':') + ";" + nl + - " shaHash = " + Util.toHexString(sha, ':') + ";" + nl + - "} Finished;" + nl; + out.print (" md5 = "); + out.print (Util.toHexString (md5Hash (), ':')); + out.println (';'); + if (prefix != null) + out.print (prefix); + out.print (" sha = "); + out.print (Util.toHexString (shaHash (), ':')); } + out.println (';'); + if (prefix != null) + out.print (prefix); + out.print ("} Finished;"); + return str.toString (); } } Deleted: trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/GNUSecurityParameters.java =================================================================== --- trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/GNUSecurityParameters.java 2007-01-07 12:48:35 UTC (rev 3019) +++ trunk/core/src/classpath/gnu/gnu/javax/net/ssl/provider/GNUSecurityParameters.java 2007-01-07 12:50:40 UTC (rev 3020) @@ -1,490 +0,0 @@ -/* GNUSecurityParameters.java -- SSL security parameters. - Copyright (C) 2006 Free Software Foundation, Inc. - -This file is a part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or (at -your option) any later version. - -GNU Classpath is distributed in the hope that it will b... [truncated message content] |