From f91d0d4e60e4e8ed3a27fe314cf1e234dbade4ad Mon Sep 17 00:00:00 2001 From: Sunita Koppar Date: Thu, 7 Oct 2010 00:59:40 -0700 Subject: [PATCH 001/139] 6714797: InitialContext.close does not close NIO socket connections Reviewed-by: asaha --- .../transport/CorbaConnectionCacheBase.java | 11 ++++++++- .../transport/CorbaTransportManagerImpl.java | 11 ++++++++- .../SocketOrChannelConnectionImpl.java | 23 +++++++++++++++++++ .../se/pept/transport/ConnectionCache.java | 6 +++++ .../se/spi/transport/CorbaConnection.java | 4 ++++ 5 files changed, 53 insertions(+), 2 deletions(-) diff --git a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaConnectionCacheBase.java b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaConnectionCacheBase.java index d8608f21ab5..0cbce53ffc1 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaConnectionCacheBase.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaConnectionCacheBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import com.sun.corba.se.pept.transport.ConnectionCache; import com.sun.corba.se.spi.logging.CORBALogDomains; import com.sun.corba.se.spi.orb.ORB; +import com.sun.corba.se.spi.transport.CorbaConnection; import com.sun.corba.se.spi.transport.CorbaConnectionCache; import com.sun.corba.se.impl.logging.ORBUtilSystemException; @@ -87,6 +88,14 @@ public abstract class CorbaConnectionCacheBase } } + public void close() { + synchronized (backingStore()) { + for (Object obj : values()) { + ((CorbaConnection)obj).closeConnectionResources() ; + } + } + } + public long numberOfIdleConnections() { long count = 0; diff --git a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java index 5f56b560a95..fae2d157969 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ import org.omg.CORBA.INTERNAL; import org.omg.CORBA.CompletionStatus; import com.sun.corba.se.pept.transport.Acceptor; +import com.sun.corba.se.pept.transport.ConnectionCache; import com.sun.corba.se.pept.transport.ByteBufferPool; import com.sun.corba.se.pept.transport.ContactInfo; import com.sun.corba.se.pept.transport.InboundConnectionCache; @@ -49,6 +50,8 @@ import com.sun.corba.se.spi.ior.ObjectAdapterId; import com.sun.corba.se.spi.orb.ORB; import com.sun.corba.se.spi.transport.CorbaAcceptor; import com.sun.corba.se.spi.transport.CorbaTransportManager; +import com.sun.corba.se.pept.transport.Connection; +import com.sun.corba.se.pept.transport.ConnectionCache; // REVISIT - impl/poa specific: import com.sun.corba.se.impl.oa.poa.Policies; @@ -182,6 +185,12 @@ public class CorbaTransportManagerImpl if (orb.transportDebugFlag) { dprint(".close->"); } + for (Object cc : outboundConnectionCaches.values()) { + ((ConnectionCache)cc).close() ; + } + for (Object cc : inboundConnectionCaches.values()) { + ((ConnectionCache)cc).close() ; + } getSelector(0).close(); } finally { if (orb.transportDebugFlag) { diff --git a/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java index e294067184e..913cd903755 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java @@ -811,6 +811,7 @@ public class SocketOrChannelConnectionImpl dprint(".close: " + this, e); } } + closeConnectionResources(); } finally { if (orb.transportDebugFlag) { dprint(".close<-: " + this); @@ -818,6 +819,28 @@ public class SocketOrChannelConnectionImpl } } + public void closeConnectionResources() { + if (orb.transportDebugFlag) { + dprint(".closeConnectionResources->: " + this); + } + Selector selector = orb.getTransportManager().getSelector(0); + selector.unregisterForEvent(this); + try { + if (socketChannel != null) + socketChannel.close() ; + if (socket != null && !socket.isClosed()) + socket.close() ; + } catch (IOException e) { + if (orb.transportDebugFlag) { + dprint( ".closeConnectionResources: " + this, e ) ; + } + } + if (orb.transportDebugFlag) { + dprint(".closeConnectionResources<-: " + this); + } + } + + public Acceptor getAcceptor() { return acceptor; diff --git a/corba/src/share/classes/com/sun/corba/se/pept/transport/ConnectionCache.java b/corba/src/share/classes/com/sun/corba/se/pept/transport/ConnectionCache.java index d5bee7d927f..ac926d063c0 100644 --- a/corba/src/share/classes/com/sun/corba/se/pept/transport/ConnectionCache.java +++ b/corba/src/share/classes/com/sun/corba/se/pept/transport/ConnectionCache.java @@ -41,6 +41,12 @@ public interface ConnectionCache public long numberOfBusyConnections(); public boolean reclaim(); + + /** Close all connections in the connection cache. + * This is used as a final cleanup, and will result + * in abrupt termination of any pending communications. + */ + public void close(); } // End of file. diff --git a/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnection.java b/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnection.java index b0e3f6f04dc..c7ec1ac0aa1 100644 --- a/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnection.java +++ b/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnection.java @@ -163,6 +163,10 @@ public interface CorbaConnection // REVISIT - MessageMediator parameter? public void serverRequestProcessingBegins(); public void serverRequestProcessingEnds(); + + /** Clean up all connection resources. Used when shutting down an ORB. + */ + public void closeConnectionResources(); } // End of file. From 7720bcf09cf6dd5aa90a371882d25dbbe9683618 Mon Sep 17 00:00:00 2001 From: Sunita Koppar Date: Thu, 7 Oct 2010 00:49:05 -0700 Subject: [PATCH 002/139] 6893109: memory leak in readObject() and writeObject() using idlj from jdk 1.6.0_14 Reviewed-by: asaha --- .../tools/corba/se/idl/toJavaPortable/Stub.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Stub.java b/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Stub.java index 3efe5609535..2020fd68f89 100644 --- a/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Stub.java +++ b/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Stub.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -344,17 +344,26 @@ public class Stub implements AuxGen stream.println (" String str = s.readUTF ();"); stream.println (" String[] args = null;"); stream.println (" java.util.Properties props = null;"); - stream.println (" org.omg.CORBA.Object obj = org.omg.CORBA.ORB.init (args, props).string_to_object (str);"); - stream.println (" org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();"); + stream.println (" org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init (args, props);"); + stream.println (" try {"); + stream.println (" org.omg.CORBA.Object obj = orb.string_to_object (str);"); stream.println (" _set_delegate (delegate);"); + stream.println (" } finally {"); + stream.println (" orb.destroy() ;"); + stream.println (" }"); stream.println (" }"); stream.println (); stream.println (" private void writeObject (java.io.ObjectOutputStream s) throws java.io.IOException"); stream.println (" {"); stream.println (" String[] args = null;"); stream.println (" java.util.Properties props = null;"); - stream.println (" String str = org.omg.CORBA.ORB.init (args, props).object_to_string (this);"); + stream.println (" org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init (args, props);"); + stream.println (" try {"); + stream.println (" String str = orb.object_to_string (this);"); stream.println (" s.writeUTF (str);"); + stream.println (" } finally {"); + stream.println (" orb.destroy() ;"); + stream.println (" }"); stream.println (" }"); } From d22fa91e8641aff09ee90c20deb7b054d39fbe07 Mon Sep 17 00:00:00 2001 From: Sunita Koppar Date: Thu, 7 Oct 2010 00:51:42 -0700 Subject: [PATCH 003/139] 6896157: unsynchronized hashmap in com.sun.corba.se.impl.transport.SelectorImpl.createReaderThread Reviewed-by: asaha --- .../corba/se/impl/transport/SelectorImpl.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java index 8686439b84f..1c60088a7a3 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.ArrayList; import java.util.HashMap; +import java.util.Map; import java.util.Iterator; import java.util.List; @@ -66,7 +67,7 @@ public class SelectorImpl private List deferredRegistrations; private List interestOpsList; private HashMap listenerThreads; - private HashMap readerThreads; + private Map readerThreads; private boolean selectorStarted; private boolean closed; private ORBUtilSystemException wrapper ; @@ -81,7 +82,7 @@ public class SelectorImpl deferredRegistrations = new ArrayList(); interestOpsList = new ArrayList(); listenerThreads = new HashMap(); - readerThreads = new HashMap(); + readerThreads = java.util.Collections.synchronizedMap(new HashMap()); closed = false; wrapper = ORBUtilSystemException.get(orb,CORBALogDomains.RPC_TRANSPORT); } @@ -178,8 +179,13 @@ public class SelectorImpl } if (eventHandler.shouldUseSelectThreadToWait()) { - SelectionKey selectionKey = eventHandler.getSelectionKey(); - selectionKey.cancel(); + SelectionKey selectionKey ; + synchronized(deferredRegistrations) { + selectionKey = eventHandler.getSelectionKey(); + } + if (selectionKey != null) { + selectionKey.cancel(); + } selector.wakeup(); return; } From a30e55aedd15f22214327e9f6c27d0a87092a8e0 Mon Sep 17 00:00:00 2001 From: Sunita Koppar Date: Thu, 7 Oct 2010 00:53:49 -0700 Subject: [PATCH 004/139] 6929137: java-corba: Locking too broad in com.sun.corba.se.impl.protocol.CorbaClientRequestDispatcherImpl Reviewed-by: asaha --- .../protocol/CorbaClientRequestDispatcherImpl.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java index 5c7555f3c70..d44873bd787 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,9 +122,6 @@ public class CorbaClientRequestDispatcherImpl implements ClientRequestDispatcher { - // Used for locking - private Object lock = new Object(); - public OutputObject beginRequest(Object self, String opName, boolean isOneWay, ContactInfo contactInfo) { @@ -151,7 +148,8 @@ public class CorbaClientRequestDispatcherImpl // This locking is done so that multiple connections are not created // for the same endpoint - synchronized (lock) { + //6929137 - Synchronized on contactInfo to avoid blocking across multiple endpoints + synchronized (contactInfo) { if (contactInfo.isConnectionBased()) { if (contactInfo.shouldCacheConnection()) { connection = (CorbaConnection) @@ -256,7 +254,7 @@ public class CorbaClientRequestDispatcherImpl registerWaiter(messageMediator); // Do connection reclaim now - synchronized (lock) { + synchronized (contactInfo) { if (contactInfo.isConnectionBased()) { if (contactInfo.shouldCacheConnection()) { OutboundConnectionCache connectionCache = From 9c7a01ef27f20d185410bc72765e02bf92beaab8 Mon Sep 17 00:00:00 2001 From: Sunita Koppar Date: Thu, 7 Oct 2010 01:03:51 -0700 Subject: [PATCH 005/139] 6948223: Corba issue, fail to reload object Reviewed-by: asaha --- .../sun/corba/se/impl/oa/poa/AOMEntry.java | 28 +++++++++++++++++-- .../impl/oa/poa/POAPolicyMediatorBase_R.java | 10 ++----- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/AOMEntry.java b/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/AOMEntry.java index b7564e716e4..d906afef923 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/AOMEntry.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/AOMEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,10 @@ import com.sun.corba.se.spi.orbutil.fsm.StateEngineFactory ; import com.sun.corba.se.impl.orbutil.concurrent.Mutex ; import com.sun.corba.se.impl.orbutil.concurrent.CondVar ; +import org.omg.CORBA.SystemException ; + +import org.omg.PortableServer.POAPackage.ObjectAlreadyActive ; + /** AOMEntry represents a Servant or potential Servant in the ActiveObjectMap. * It may be in several states to allow for long incarnate or etherealize operations. * The methods on this class mostly represent input symbols to the state machine @@ -121,6 +125,12 @@ public class AOMEntry extends FSMImpl { } } ; + private static Action oaaAction = new ActionBase( "throwObjectAlreadyActive" ) { + public void doIt( FSM fsm, Input in ) { + throw new RuntimeException( new ObjectAlreadyActive() ) ; + } + } ; + private static Guard waitGuard = new GuardBase( "wait" ) { public Guard.Result evaluate( FSM fsm, Input in ) { AOMEntry entry = (AOMEntry)fsm ; @@ -173,19 +183,23 @@ public class AOMEntry extends FSMImpl { engine.add( INCARN, START_ETH, waitGuard, null, INCARN ) ; engine.add( INCARN, INC_DONE, null, VALID ) ; engine.add( INCARN, INC_FAIL, decrementAction, INVALID ) ; + engine.add( INCARN, ACTIVATE, oaaAction, INCARN ) ; engine.add( VALID, ENTER, incrementAction, VALID ) ; engine.add( VALID, EXIT, decrementAction, VALID ) ; engine.add( VALID, START_ETH, greaterZeroGuard, null, ETHP ) ; engine.add( VALID, START_ETH, zeroGuard, null, ETH ) ; + engine.add( VALID, ACTIVATE, oaaAction, VALID ) ; engine.add( ETHP, ENTER, waitGuard, null, ETHP ) ; engine.add( ETHP, START_ETH, null, ETHP ) ; engine.add( ETHP, EXIT, greaterOneGuard, decrementAction, ETHP ) ; engine.add( ETHP, EXIT, oneGuard, decrementAction, ETH ) ; + engine.add( ETHP, ACTIVATE, oaaAction, ETHP ) ; engine.add( ETH, START_ETH, null, ETH ) ; engine.add( ETH, ETH_DONE, null, DESTROYED ) ; + engine.add( ETH, ACTIVATE, oaaAction, ETH ) ; engine.add( ETH, ENTER, waitGuard, null, ETH ) ; engine.setDefault( DESTROYED, throwIllegalStateExceptionAction, DESTROYED ) ; @@ -217,7 +231,17 @@ public class AOMEntry extends FSMImpl { public void etherealizeComplete() { doIt( ETH_DONE ) ; } public void incarnateComplete() { doIt( INC_DONE ) ; } public void incarnateFailure() { doIt( INC_FAIL ) ; } - public void activateObject() { doIt( ACTIVATE ) ; } + public void activateObject() throws ObjectAlreadyActive { + try { + doIt( ACTIVATE ) ; + } catch (RuntimeException exc) { + Throwable thr = exc.getCause() ; + if (thr instanceof ObjectAlreadyActive) + throw (ObjectAlreadyActive)thr ; + else + throw exc ; + } + } public void enter() { doIt( ENTER ) ; } public void exit() { doIt( EXIT ) ; } } diff --git a/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase_R.java b/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase_R.java index b396ac5227d..1bc9130e109 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase_R.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase_R.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,13 +107,9 @@ public abstract class POAPolicyMediatorBase_R extends POAPolicyMediatorBase { throw new ServantAlreadyActive(); ActiveObjectMap.Key key = new ActiveObjectMap.Key( id ) ; - // Note that this can't happen for system assigned IDs since the - // POA never hands out the same ID. However, we make this redundant - // check here to share the code. - if (activeObjectMap.containsKey(key)) - throw new ObjectAlreadyActive() ; - AOMEntry entry = activeObjectMap.get( key ) ; + + // Check for an ObjectAlreadyActive error entry.activateObject() ; activateServant( key, entry, servant ) ; } From 2a322bbd1dd5539491dc3d030f1fc7b8539ba50e Mon Sep 17 00:00:00 2001 From: John R Rose Date: Sat, 30 Oct 2010 21:02:30 -0700 Subject: [PATCH 006/139] 6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions JDK changes which run atop the corresponding JVM hook Reviewed-by: never, twisti --- .../share/classes/java/dyn/MethodHandle.java | 7 +- .../share/classes/java/dyn/MethodHandles.java | 58 ++- .../classes/sun/dyn/AdapterMethodHandle.java | 33 ++ .../classes/sun/dyn/BoundMethodHandle.java | 2 +- .../share/classes/sun/dyn/InvokeGeneric.java | 160 ++++++ jdk/src/share/classes/sun/dyn/Invokers.java | 17 + .../classes/sun/dyn/MethodHandleImpl.java | 9 +- .../classes/sun/dyn/MethodHandleNatives.java | 14 + .../share/classes/sun/dyn/MethodTypeImpl.java | 2 + .../sun/dyn/util/ValueConversions.java | 71 ++- jdk/test/java/dyn/InvokeGenericTest.java | 484 ++++++++++++++++++ jdk/test/java/dyn/MethodHandlesTest.java | 2 +- 12 files changed, 847 insertions(+), 12 deletions(-) create mode 100644 jdk/src/share/classes/sun/dyn/InvokeGeneric.java create mode 100644 jdk/test/java/dyn/InvokeGenericTest.java diff --git a/jdk/src/share/classes/java/dyn/MethodHandle.java b/jdk/src/share/classes/java/dyn/MethodHandle.java index 4904e975306..251d338ce53 100644 --- a/jdk/src/share/classes/java/dyn/MethodHandle.java +++ b/jdk/src/share/classes/java/dyn/MethodHandle.java @@ -329,6 +329,7 @@ public abstract class MethodHandle public final Object invokeVarargs(Object... arguments) throws Throwable { int argc = arguments == null ? 0 : arguments.length; MethodType type = type(); + if (type.parameterCount() != argc) throw badParameterCount(type, argc); if (argc <= 10) { MethodHandle invoker = MethodHandles.invokers(type).genericInvoker(); switch (argc) { @@ -377,6 +378,10 @@ public abstract class MethodHandle return invokeVarargs(arguments.toArray()); } + private static WrongMethodTypeException badParameterCount(MethodType type, int argc) { + return new WrongMethodTypeException(type+" does not take "+argc+" parameters"); + } + /* --- this is intentionally NOT a javadoc yet --- * PROVISIONAL API, WORK IN PROGRESS: * Produce an adapter method handle which adapts the type of the @@ -446,7 +451,7 @@ public abstract class MethodHandle * @throws IllegalArgumentException if the conversion cannot be made * @see MethodHandles#convertArguments */ - public final MethodHandle asType(MethodType newType) { + public MethodHandle asType(MethodType newType) { return MethodHandles.convertArguments(this, newType); } diff --git a/jdk/src/share/classes/java/dyn/MethodHandles.java b/jdk/src/share/classes/java/dyn/MethodHandles.java index b6e83338340..3e1fef7ff14 100644 --- a/jdk/src/share/classes/java/dyn/MethodHandles.java +++ b/jdk/src/share/classes/java/dyn/MethodHandles.java @@ -1068,10 +1068,14 @@ public class MethodHandles { MethodType oldType = target.type(); if (oldType.equals(newType)) return target; - MethodHandle res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target, - newType, oldType, null); + MethodHandle res = null; + try { + res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target, + newType, oldType, null); + } catch (IllegalArgumentException ex) { + } if (res == null) - throw newIllegalArgumentException("cannot convert to "+newType+": "+target); + throw new WrongMethodTypeException("cannot convert to "+newType+": "+target); return res; } @@ -1392,6 +1396,20 @@ public class MethodHandles { return adapter; } + /** Apply the given filter function to the return value of the given target. + */ + /*public*/ static + MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) { + MethodType targetType = target.type(); + MethodType filterType = filter.type(); + if (filterType.parameterCount() != 1 + || filterType.parameterType(0) != targetType.returnType()) + throw newIllegalArgumentException("target and filter types do not match"); + // FIXME: Too many nodes here. + MethodHandle returner = dropArguments(filter, 0, targetType.parameterList()); + return foldArguments(returner, exactInvoker(target.type()).bindTo(target)); + } + /** * PROVISIONAL API, WORK IN PROGRESS: * Adapt a target method handle {@code target} by pre-processing @@ -1434,7 +1452,7 @@ public class MethodHandles { * @return method handle which incorporates the specified argument folding logic * @throws IllegalArgumentException if the first argument type of * {@code target} is not the same as {@code combiner}'s return type, - * or if the next {@code foldArgs} argument types of {@code target} + * or if the following argument types of {@code target} * are not identical with the argument types of {@code combiner} */ public static @@ -1443,12 +1461,39 @@ public class MethodHandles { MethodType combinerType = combiner.type(); int foldArgs = combinerType.parameterCount(); boolean ok = (targetType.parameterCount() >= 1 + foldArgs); + if (ok && !combinerType.parameterList().equals(targetType.parameterList().subList(1, foldArgs+1))) + ok = false; + if (ok && !combinerType.returnType().equals(targetType.parameterType(0))) + ok = false; if (!ok) throw misMatchedTypes("target and combiner types", targetType, combinerType); MethodType newType = targetType.dropParameterTypes(0, 1); return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, newType, combiner); } + // /** + // * PROVISIONAL API, WORK IN PROGRESS: + // * Adapt a target method handle {@code target} by pre-processing + // * some of its arguments to derive a new target method handle. + // * Call the new target on the original arguments. + // * @param combined method handle to call initially on the incoming arguments + // * @return method handle which incorporates the specified dispatching logic + // * @throws IllegalArgumentException if the first argument type of + // * {@code combiner}'s return type is not {@link MethodHandle}, + // * or if the next argument types of {@code target} + // * are not identical with the argument types of {@code combiner} + // */ + // public static + // MethodHandle dispatchArguments(MethodType targetType, MethodHandle dispatcher) { + // MethodType dispatcherType = dispatcher.type(); + // int foldArgs = dispatcherType.parameterCount(); + // boolean ok = (targetType.parameterCount() >= foldArgs); + // if (!ok) + // throw misMatchedTypes("target and dispatcher types", targetType, dispatcherType); + // MethodHandle target = exactInvoker(targetType); + // return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, targetType, dispatcher); + // } + /** * PROVISIONAL API, WORK IN PROGRESS: * Make a method handle which adapts a target method handle, @@ -1691,4 +1736,9 @@ public class MethodHandles { } return null; } + + /*non-public*/ + static MethodHandle withTypeHandler(MethodHandle target, MethodHandle typeHandler) { + return MethodHandleImpl.withTypeHandler(IMPL_TOKEN, target, typeHandler); + } } diff --git a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java b/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java index fb9b7fa26c2..65bbd372b9c 100644 --- a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java +++ b/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java @@ -478,6 +478,39 @@ public class AdapterMethodHandle extends BoundMethodHandle { return new AdapterMethodHandle(target, newType, makeConv(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY)); } + static MethodHandle makeTypeHandler(Access token, + MethodHandle target, MethodHandle typeHandler) { + Access.check(token); + return new WithTypeHandler(target, typeHandler); + } + + static class WithTypeHandler extends AdapterMethodHandle { + final MethodHandle target, typeHandler; + WithTypeHandler(MethodHandle target, MethodHandle typeHandler) { + super(target, target.type(), OP_RETYPE_ONLY); + this.target = target; + this.typeHandler = typeHandler.asType(TYPE_HANDLER_TYPE); + } + + public MethodHandle asType(MethodType newType) { + if (this.type() == newType) + return this; + try { + MethodHandle retyped = (MethodHandle) typeHandler.invokeExact(target, newType); + // Contract: Must return the desired type, or throw WMT + if (retyped.type() != newType) + throw new WrongMethodTypeException(retyped.toString()); + return retyped; + } catch (Throwable ex) { + if (ex instanceof Error) throw (Error)ex; + if (ex instanceof RuntimeException) throw (RuntimeException)ex; + throw new RuntimeException(ex); + } + } + private static final MethodType TYPE_HANDLER_TYPE + = MethodType.methodType(MethodHandle.class, MethodHandle.class, MethodType.class); + } + /** Can a checkcast adapter validly convert the target to newType? * The JVM supports all kind of reference casts, even silly ones. */ diff --git a/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java b/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java index f2ae32efbc9..4f25262f46f 100644 --- a/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java +++ b/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java @@ -103,7 +103,7 @@ public class BoundMethodHandle extends MethodHandle { super(Access.TOKEN, type); this.argument = argument; this.vmargslot = vmargslot; - assert(this.getClass() == AdapterMethodHandle.class); + assert(this instanceof AdapterMethodHandle); } /** Initialize the current object as a Java method handle, binding it diff --git a/jdk/src/share/classes/sun/dyn/InvokeGeneric.java b/jdk/src/share/classes/sun/dyn/InvokeGeneric.java new file mode 100644 index 00000000000..8137bb4a67a --- /dev/null +++ b/jdk/src/share/classes/sun/dyn/InvokeGeneric.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.dyn; + +import java.dyn.*; +import java.lang.reflect.*; +import sun.dyn.util.*; + +/** + * Adapters which manage MethodHanndle.invokeGeneric calls. + * The JVM calls one of these when the exact type match fails. + * @author jrose + */ +class InvokeGeneric { + // erased type for the call, which originates from an invokeGeneric site + private final MethodType erasedCallerType; + // an invoker of type (MT, MH; A...) -> R + private final MethodHandle initialInvoker; + + /** Compute and cache information for this adapter, so that it can + * call out to targets of the erasure-family of the given erased type. + */ + private InvokeGeneric(MethodType erasedCallerType) throws NoAccessException { + this.erasedCallerType = erasedCallerType; + this.initialInvoker = makeInitialInvoker(); + assert initialInvoker.type().equals(erasedCallerType + .insertParameterTypes(0, MethodType.class, MethodHandle.class)) + : initialInvoker.type(); + } + + private static MethodHandles.Lookup lookup() { + return MethodHandleImpl.IMPL_LOOKUP; + } + + /** Return the adapter information for this type's erasure. */ + static MethodHandle genericInvokerOf(MethodType type) { + MethodTypeImpl form = MethodTypeImpl.of(type); + MethodHandle genericInvoker = form.genericInvoker; + if (genericInvoker == null) { + try { + InvokeGeneric gen = new InvokeGeneric(form.erasedType()); + form.genericInvoker = genericInvoker = gen.initialInvoker; + } catch (NoAccessException ex) { + throw new RuntimeException(ex); + } + } + return genericInvoker; + } + + private MethodHandle makeInitialInvoker() throws NoAccessException { + // postDispatch = #(MH'; MT, MH; A...){MH'(MT, MH; A)} + MethodHandle postDispatch = makePostDispatchInvoker(); + MethodHandle invoker; + if (returnConversionPossible()) { + invoker = MethodHandles.foldArguments(postDispatch, + dispatcher("dispatchWithConversion")); + } else { + invoker = MethodHandles.foldArguments(postDispatch, dispatcher("dispatch")); + } + return invoker; + } + + private static final Class[] EXTRA_ARGS = { MethodType.class, MethodHandle.class }; + private MethodHandle makePostDispatchInvoker() { + // Take (MH'; MT, MH; A...) and run MH'(MT, MH; A...). + MethodType invokerType = erasedCallerType.insertParameterTypes(0, EXTRA_ARGS); + return MethodHandles.exactInvoker(invokerType); + } + private MethodHandle dropDispatchArguments(MethodHandle targetInvoker) { + assert(targetInvoker.type().parameterType(0) == MethodHandle.class); + return MethodHandles.dropArguments(targetInvoker, 1, EXTRA_ARGS); + } + + private MethodHandle dispatcher(String dispatchName) throws NoAccessException { + return lookup().bind(this, dispatchName, + MethodType.methodType(MethodHandle.class, + MethodType.class, MethodHandle.class)); + } + + static final boolean USE_AS_TYPE_PATH = true; + + /** Return a method handle to invoke on the callerType, target, and remaining arguments. + * The method handle must finish the call. + * This is the first look at the caller type and target. + */ + private MethodHandle dispatch(MethodType callerType, MethodHandle target) { + MethodType targetType = target.type(); + if (USE_AS_TYPE_PATH || target instanceof AdapterMethodHandle.WithTypeHandler) { + MethodHandle newTarget = target.asType(callerType); + targetType = callerType; + Invokers invokers = MethodTypeImpl.invokers(Access.TOKEN, targetType); + MethodHandle invoker = invokers.erasedInvokerWithDrops; + if (invoker == null) { + invokers.erasedInvokerWithDrops = invoker = + dropDispatchArguments(invokers.erasedInvoker()); + } + return invoker.bindTo(newTarget); + } + throw new RuntimeException("NYI"); + } + + private MethodHandle dispatchWithConversion(MethodType callerType, MethodHandle target) { + MethodHandle finisher = dispatch(callerType, target); + if (returnConversionNeeded(callerType, target)) + finisher = addReturnConversion(finisher, callerType.returnType()); //FIXME: slow + return finisher; + } + + private boolean returnConversionPossible() { + Class needType = erasedCallerType.returnType(); + return !needType.isPrimitive(); + } + private boolean returnConversionNeeded(MethodType callerType, MethodHandle target) { + Class needType = callerType.returnType(); + if (needType == erasedCallerType.returnType()) + return false; // no conversions possible, since must be primitive or Object + Class haveType = target.type().returnType(); + if (VerifyType.isNullConversion(haveType, needType)) + return false; + return true; + } + private MethodHandle addReturnConversion(MethodHandle target, Class type) { + if (true) throw new RuntimeException("NYI"); + // FIXME: This is slow because it creates a closure node on every call that requires a return cast. + MethodType targetType = target.type(); + MethodHandle caster = ValueConversions.identity(type); + caster = caster.asType(MethodType.methodType(type, targetType.returnType())); + // Drop irrelevant arguments, because we only care about the return value: + caster = MethodHandles.dropArguments(caster, 1, targetType.parameterList()); + MethodHandle result = MethodHandles.foldArguments(caster, target); + return result.asType(target.type()); + } + + public String toString() { + return "InvokeGeneric"+erasedCallerType; + } +} diff --git a/jdk/src/share/classes/sun/dyn/Invokers.java b/jdk/src/share/classes/sun/dyn/Invokers.java index b3d2823d024..2f2c92a779f 100644 --- a/jdk/src/share/classes/sun/dyn/Invokers.java +++ b/jdk/src/share/classes/sun/dyn/Invokers.java @@ -38,6 +38,10 @@ public class Invokers { // exact invoker for the outgoing call private /*lazy*/ MethodHandle exactInvoker; + // erased (partially untyped but with primitives) invoker for the outgoing call + private /*lazy*/ MethodHandle erasedInvoker; + /*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric + // generic (untyped) invoker for the outgoing call private /*lazy*/ MethodHandle genericInvoker; @@ -80,6 +84,19 @@ public class Invokers { return invoker; } + public MethodHandle erasedInvoker() { + MethodHandle invoker1 = exactInvoker(); + MethodHandle invoker = erasedInvoker; + if (invoker != null) return invoker; + MethodType erasedType = targetType.erase(); + if (erasedType == targetType.generic()) + invoker = genericInvoker(); + else + invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType)); + erasedInvoker = invoker; + return invoker; + } + public MethodHandle varargsInvoker(int objectArgCount) { MethodHandle vaInvoker = varargsInvokers[objectArgCount]; if (vaInvoker != null) return vaInvoker; diff --git a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java index caa96b90d69..49a625367a4 100644 --- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java +++ b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java @@ -560,7 +560,9 @@ public abstract class MethodHandleImpl { MethodHandle bindReceiver(Access token, MethodHandle target, Object receiver) { Access.check(token); - if (target instanceof AdapterMethodHandle) { + if (target instanceof AdapterMethodHandle && + ((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY + ) { Object info = MethodHandleNatives.getTargetInfo(target); if (info instanceof DirectMethodHandle) { DirectMethodHandle dmh = (DirectMethodHandle) info; @@ -1257,4 +1259,9 @@ public abstract class MethodHandleImpl { Access.check(token); return MethodHandleNatives.getBootstrap(callerClass); } + + public static MethodHandle withTypeHandler(Access token, MethodHandle target, MethodHandle typeHandler) { + Access.check(token); + return AdapterMethodHandle.makeTypeHandler(token, target, typeHandler); + } } diff --git a/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java b/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java index 47a9a2d3de1..3d0629dd034 100644 --- a/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java +++ b/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java @@ -316,6 +316,20 @@ class MethodHandleNatives { return MethodTypeImpl.makeImpl(Access.TOKEN, rtype, ptypes, true); } + /** + * The JVM wants to use a MethodType with invokeGeneric. Give the runtime fair warning. + */ + static void notifyGenericMethodType(MethodType type) { + try { + // Trigger adapter creation. + InvokeGeneric.genericInvokerOf(type); + } catch (Exception ex) { + Error err = new InternalError("Exception while resolving invokeGeneric"); + err.initCause(ex); + throw err; + } + } + /** * The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help. * It will make an up-call to this method. (Do not change the name or signature.) diff --git a/jdk/src/share/classes/sun/dyn/MethodTypeImpl.java b/jdk/src/share/classes/sun/dyn/MethodTypeImpl.java index 0a318148a73..059f2697542 100644 --- a/jdk/src/share/classes/sun/dyn/MethodTypeImpl.java +++ b/jdk/src/share/classes/sun/dyn/MethodTypeImpl.java @@ -48,6 +48,7 @@ public class MethodTypeImpl { final long primCounts; // packed prim & double counts final int vmslots; // total number of parameter slots final MethodType erasedType; // the canonical erasure + /*lazy*/ MethodType primsAsBoxes; // replace prims by wrappers /*lazy*/ MethodType primArgsAsBoxes; // wrap args only; make raw return /*lazy*/ MethodType primsAsInts; // replace prims by int/long @@ -59,6 +60,7 @@ public class MethodTypeImpl { /*lazy*/ FromGeneric fromGeneric; // convert cs. w/o prims to with /*lazy*/ SpreadGeneric[] spreadGeneric; // expand one argument to many /*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly + /*lazy*/ MethodHandle genericInvoker; // hook for invokeGeneric public MethodType erasedType() { return erasedType; diff --git a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java b/jdk/src/share/classes/sun/dyn/util/ValueConversions.java index f5ee5cb81fd..aeacb9e0f0f 100644 --- a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java +++ b/jdk/src/share/classes/sun/dyn/util/ValueConversions.java @@ -377,7 +377,7 @@ public class ValueConversions { REBOX_CONVERSIONS = newWrapperCaches(2); /** - * Becase we normalize primitive types to reduce the number of signatures, + * Because we normalize primitive types to reduce the number of signatures, * primitives are sometimes manipulated under an "erased" type, * either int (for types other than long/double) or long (for all types). * When the erased primitive value is then boxed into an Integer or Long, @@ -475,10 +475,10 @@ public class ValueConversions { } private static final EnumMap[] - ZERO_CONSTANT_FUNCTIONS = newWrapperCaches(1); + CONSTANT_FUNCTIONS = newWrapperCaches(2); public static MethodHandle zeroConstantFunction(Wrapper wrap) { - EnumMap cache = ZERO_CONSTANT_FUNCTIONS[0]; + EnumMap cache = CONSTANT_FUNCTIONS[0]; MethodHandle mh = cache.get(wrap); if (mh != null) { return mh; @@ -543,6 +543,24 @@ public class ValueConversions { return x; } + /** + * Identity function on ints. + * @param x an arbitrary int value + * @return the same value x + */ + static int identity(int x) { + return x; + } + + /** + * Identity function on longs. + * @param x an arbitrary long value + * @return the same value x + */ + static long identity(long x) { + return x; + } + /** * Identity function, with reference cast. * @param t an arbitrary reference type @@ -553,7 +571,7 @@ public class ValueConversions { return t.cast(x); } - private static final MethodHandle IDENTITY, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY; + private static final MethodHandle IDENTITY, IDENTITY_I, IDENTITY_J, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY; static { try { MethodType idType = MethodType.genericMethodType(1); @@ -562,6 +580,8 @@ public class ValueConversions { MethodType ignoreType = idType.changeReturnType(void.class); MethodType zeroObjectType = MethodType.genericMethodType(0); IDENTITY = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", idType); + IDENTITY_I = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(int.class, int.class)); + IDENTITY_J = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(long.class, long.class)); //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); CAST_REFERENCE = IMPL_LOOKUP.findStatic(ValueConversions.class, "castReference", castType); ALWAYS_NULL = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysNull", idType); @@ -613,6 +633,49 @@ public class ValueConversions { return IDENTITY; } + public static MethodHandle identity(Class type) { + if (type == Object.class) + return IDENTITY; + else if (!type.isPrimitive()) + return retype(MethodType.methodType(type, type), IDENTITY); + else + return identity(Wrapper.forPrimitiveType(type)); + } + + static MethodHandle identity(Wrapper wrap) { + EnumMap cache = CONSTANT_FUNCTIONS[1]; + MethodHandle mh = cache.get(wrap); + if (mh != null) { + return mh; + } + // slow path + MethodType type = MethodType.methodType(wrap.primitiveType(), wrap.primitiveType()); + try { + mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", type); + } catch (NoAccessException ex) { + mh = null; + } + if (mh == null && wrap == Wrapper.VOID) { + mh = EMPTY; // #(){} : #()void + } + if (mh != null) { + cache.put(wrap, mh); + return mh; + } + + // use a raw conversion + if (wrap.isSingleWord() && wrap != Wrapper.INT) { + mh = retype(type, identity(Wrapper.INT)); + } else if (wrap.isDoubleWord() && wrap != Wrapper.LONG) { + mh = retype(type, identity(Wrapper.LONG)); + } + if (mh != null) { + cache.put(wrap, mh); + return mh; + } + throw new IllegalArgumentException("cannot find identity for " + wrap); + } + private static MethodHandle retype(MethodType type, MethodHandle mh) { return AdapterMethodHandle.makeRetypeOnly(IMPL_TOKEN, type, mh); } diff --git a/jdk/test/java/dyn/InvokeGenericTest.java b/jdk/test/java/dyn/InvokeGenericTest.java new file mode 100644 index 00000000000..83aa10b0202 --- /dev/null +++ b/jdk/test/java/dyn/InvokeGenericTest.java @@ -0,0 +1,484 @@ +/* + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @summary unit tests for java.dyn.MethodHandle.invokeGeneric + * @compile -target 7 InvokeGenericTest.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.InvokeGenericTest + */ + +package test.java.dyn; + +import java.dyn.*; +import static java.dyn.MethodHandles.*; +import static java.dyn.MethodType.*; +import java.lang.reflect.*; +import java.util.*; +import org.junit.*; +import static org.junit.Assert.*; +import static org.junit.Assume.*; + + +/** + * + * @author jrose + */ +public class InvokeGenericTest { + // How much output? + static int verbosity = 0; + static { + String vstr = System.getProperty("test.java.dyn.InvokeGenericTest.verbosity"); + if (vstr != null) verbosity = Integer.parseInt(vstr); + } + + @Test + public void testFirst() throws Throwable { + verbosity += 9; try { + // left blank for debugging + } finally { printCounts(); verbosity -= 9; } + } + + public InvokeGenericTest() { + } + + @Before + public void checkImplementedPlatform() { + boolean platformOK = false; + Properties properties = System.getProperties(); + String vers = properties.getProperty("java.vm.version"); + String name = properties.getProperty("java.vm.name"); + String arch = properties.getProperty("os.arch"); + if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") || + arch.equals("sparc") || arch.equals("sparcv9")) && + (name.contains("Client") || name.contains("Server")) + ) { + platformOK = true; + } else { + System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch)); + } + assumeTrue(platformOK); + } + + String testName; + static int allPosTests, allNegTests; + int posTests, negTests; + @After + public void printCounts() { + if (verbosity >= 2 && (posTests | negTests) != 0) { + System.out.println(); + if (posTests != 0) System.out.println("=== "+testName+": "+posTests+" positive test cases run"); + if (negTests != 0) System.out.println("=== "+testName+": "+negTests+" negative test cases run"); + allPosTests += posTests; + allNegTests += negTests; + posTests = negTests = 0; + } + } + void countTest(boolean positive) { + if (positive) ++posTests; + else ++negTests; + } + void countTest() { countTest(true); } + void startTest(String name) { + if (testName != null) printCounts(); + if (verbosity >= 1) + System.out.println(name); + posTests = negTests = 0; + testName = name; + } + + @BeforeClass + public static void setUpClass() throws Exception { + calledLog.clear(); + calledLog.add(null); + nextArgVal = INITIAL_ARG_VAL; + } + + @AfterClass + public static void tearDownClass() throws Exception { + int posTests = allPosTests, negTests = allNegTests; + if (verbosity >= 2 && (posTests | negTests) != 0) { + System.out.println(); + if (posTests != 0) System.out.println("=== "+posTests+" total positive test cases"); + if (negTests != 0) System.out.println("=== "+negTests+" total negative test cases"); + } + } + + static List calledLog = new ArrayList(); + static Object logEntry(String name, Object... args) { + return Arrays.asList(name, Arrays.asList(args)); + } + static Object called(String name, Object... args) { + Object entry = logEntry(name, args); + calledLog.add(entry); + return entry; + } + static void assertCalled(String name, Object... args) { + Object expected = logEntry(name, args); + Object actual = calledLog.get(calledLog.size() - 1); + if (expected.equals(actual) && verbosity < 9) return; + System.out.println("assertCalled "+name+":"); + System.out.println("expected: "+expected); + System.out.println("actual: "+actual); + System.out.println("ex. types: "+getClasses(expected)); + System.out.println("act. types: "+getClasses(actual)); + assertEquals("previous method call", expected, actual); + } + static void printCalled(MethodHandle target, String name, Object... args) { + if (verbosity >= 3) + System.out.println("calling MH="+target+" to "+name+Arrays.toString(args)); + } + + static Object castToWrapper(Object value, Class dst) { + Object wrap = null; + if (value instanceof Number) + wrap = castToWrapperOrNull(((Number)value).longValue(), dst); + if (value instanceof Character) + wrap = castToWrapperOrNull((char)(Character)value, dst); + if (wrap != null) return wrap; + return dst.cast(value); + } + + static Object castToWrapperOrNull(long value, Class dst) { + if (dst == int.class || dst == Integer.class) + return (int)(value); + if (dst == long.class || dst == Long.class) + return (long)(value); + if (dst == char.class || dst == Character.class) + return (char)(value); + if (dst == short.class || dst == Short.class) + return (short)(value); + if (dst == float.class || dst == Float.class) + return (float)(value); + if (dst == double.class || dst == Double.class) + return (double)(value); + if (dst == byte.class || dst == Byte.class) + return (byte)(value); + if (dst == boolean.class || dst == boolean.class) + return ((value % 29) & 1) == 0; + return null; + } + + static final int ONE_MILLION = (1000*1000), // first int value + TEN_BILLION = (10*1000*1000*1000), // scale factor to reach upper 32 bits + INITIAL_ARG_VAL = ONE_MILLION << 1; // <<1 makes space for sign bit; + static long nextArgVal; + static long nextArg(boolean moreBits) { + long val = nextArgVal++; + long sign = -(val & 1); // alternate signs + val >>= 1; + if (moreBits) + // Guarantee some bits in the high word. + // In any case keep the decimal representation simple-looking, + // with lots of zeroes, so as not to make the printed decimal + // strings unnecessarily noisy. + val += (val % ONE_MILLION) * TEN_BILLION; + return val ^ sign; + } + static int nextArg() { + // Produce a 32-bit result something like ONE_MILLION+(smallint). + // Example: 1_000_042. + return (int) nextArg(false); + } + static long nextArg(Class kind) { + if (kind == long.class || kind == Long.class || + kind == double.class || kind == Double.class) + // produce a 64-bit result something like + // ((TEN_BILLION+1) * (ONE_MILLION+(smallint))) + // Example: 10_000_420_001_000_042. + return nextArg(true); + return (long) nextArg(); + } + + static Object randomArg(Class param) { + Object wrap = castToWrapperOrNull(nextArg(param), param); + if (wrap != null) { + return wrap; + } +// import sun.dyn.util.Wrapper; +// Wrapper wrap = Wrapper.forBasicType(dst); +// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst)) +// wrap = Wrapper.forWrapperType(dst); +// if (wrap != Wrapper.OBJECT) +// return wrap.wrap(nextArg++); + if (param.isInterface()) { + for (Class c : param.getClasses()) { + if (param.isAssignableFrom(c) && !c.isInterface()) + { param = c; break; } + } + } + if (param.isInterface() || param.isAssignableFrom(String.class)) + return "#"+nextArg(); + else + try { + return param.newInstance(); + } catch (InstantiationException ex) { + } catch (IllegalAccessException ex) { + } + return null; // random class not Object, String, Integer, etc. + } + static Object[] randomArgs(Class... params) { + Object[] args = new Object[params.length]; + for (int i = 0; i < args.length; i++) + args[i] = randomArg(params[i]); + return args; + } + static Object[] randomArgs(int nargs, Class param) { + Object[] args = new Object[nargs]; + for (int i = 0; i < args.length; i++) + args[i] = randomArg(param); + return args; + } + + static final Object ANON_OBJ = new Object(); + static Object zeroArg(Class param) { + Object x = castToWrapperOrNull(0L, param); + if (x != null) return x; + if (param.isInterface() || param.isAssignableFrom(String.class)) return "\"\""; + if (param == Object.class) return ANON_OBJ; + if (param.getComponentType() != null) return Array.newInstance(param.getComponentType(), 0); + return null; + } + static Object[] zeroArgs(Class... params) { + Object[] args = new Object[params.length]; + for (int i = 0; i < args.length; i++) + args[i] = zeroArg(params[i]); + return args; + } + static Object[] zeroArgs(List> params) { + return zeroArgs(params.toArray(new Class[0])); + } + + static T[] array(Class atype, E... a) { + return Arrays.copyOf(a, a.length, atype); + } + static T[] cat(T[] a, T... b) { + int alen = a.length, blen = b.length; + if (blen == 0) return a; + T[] c = Arrays.copyOf(a, alen + blen); + System.arraycopy(b, 0, c, alen, blen); + return c; + } + static Integer[] boxAll(int... vx) { + Integer[] res = new Integer[vx.length]; + for (int i = 0; i < res.length; i++) { + res[i] = vx[i]; + } + return res; + } + static Object getClasses(Object x) { + if (x == null) return x; + if (x instanceof String) return x; // keep the name + if (x instanceof List) { + // recursively report classes of the list elements + Object[] xa = ((List)x).toArray(); + for (int i = 0; i < xa.length; i++) + xa[i] = getClasses(xa[i]); + return Arrays.asList(xa); + } + return x.getClass().getSimpleName(); + } + + static MethodHandle changeArgTypes(MethodHandle target, Class argType) { + return changeArgTypes(target, 0, 999, argType); + } + static MethodHandle changeArgTypes(MethodHandle target, + int beg, int end, Class argType) { + MethodType targetType = target.type(); + end = Math.min(end, targetType.parameterCount()); + ArrayList> argTypes = new ArrayList>(targetType.parameterList()); + Collections.fill(argTypes.subList(beg, end), argType); + MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes); + return MethodHandles.convertArguments(target, ttype2); + } + + // This lookup is good for all members in and under InvokeGenericTest. + static final Lookup LOOKUP = MethodHandles.lookup(); + + Map>, MethodHandle> CALLABLES = new HashMap>, MethodHandle>(); + MethodHandle callable(List> params) { + MethodHandle mh = CALLABLES.get(params); + if (mh == null) { + mh = collectArguments(collector_MH, methodType(Object.class, params)); + CALLABLES.put(params, mh); + } + return mh; + } + MethodHandle callable(Class... params) { + return callable(Arrays.asList(params)); + } + private static Object collector(Object... args) { + return Arrays.asList(args); + } + private static final MethodHandle collector_MH; + static { + try { + collector_MH + = LOOKUP.findStatic(LOOKUP.lookupClass(), + "collector", + methodType(Object.class, Object[].class)); + } catch (NoAccessException ex) { + throw new RuntimeException(ex); + } + } + + @Test + public void testSimple() throws Throwable { + startTest("testSimple"); + countTest(); + String[] args = { "one", "two" }; + MethodHandle mh = callable(Object.class, String.class); + Object res; List resl; + res = resl = (List) mh.invokeGeneric((String)args[0], (Object)args[1]); + //System.out.println(res); + assertEquals(Arrays.asList(args), res); + } + + @Test + public void testWrongArgumentCount() throws Throwable { + startTest("testWrongArgumentCount"); + for (int i = 0; i <= 10; i++) { + testWrongArgumentCount(Collections.>nCopies(i, Integer.class)); + if (i <= 4) { + testWrongArgumentCount(Collections.>nCopies(i, int.class)); + testWrongArgumentCount(Collections.>nCopies(i, long.class)); + } + } + } + public void testWrongArgumentCount(List> params) throws Throwable { + int max = params.size(); + for (int i = 0; i < max; i++) { + List> params2 = params.subList(0, i); + for (int k = 0; k <= 2; k++) { + if (k == 1) params = methodType(Object.class, params).generic().parameterList(); + if (k == 2) params2 = methodType(Object.class, params2).generic().parameterList(); + testWrongArgumentCount(params, params2); + testWrongArgumentCount(params2, params); + } + } + } + public void testWrongArgumentCount(List> expect, List> observe) throws Throwable { + countTest(false); + if (expect.equals(observe)) + assert(false); + MethodHandle target = callable(expect); + Object[] args = zeroArgs(observe); + Object junk; + try { + switch (args.length) { + case 0: + junk = target.invokeGeneric(); break; + case 1: + junk = target.invokeGeneric(args[0]); break; + case 2: + junk = target.invokeGeneric(args[0], args[1]); break; + case 3: + junk = target.invokeGeneric(args[0], args[1], args[2]); break; + case 4: + junk = target.invokeGeneric(args[0], args[1], args[2], args[3]); break; + default: + junk = MethodHandles.invokeVarargs(target, args); break; + } + } catch (WrongMethodTypeException ex) { + return; + } catch (Exception ex) { + throw new RuntimeException("wrong exception calling "+target+target.type()+" on "+Arrays.asList(args)+" : "+ex); + } + throw new RuntimeException("bad success calling "+target+target.type()+" on "+Arrays.asList(args)); + } + + /** Make a list of all combinations of the given types, with the given arities. + * A void return type is possible iff the first type is void.class. + */ + static List allMethodTypes(int minargc, int maxargc, Class... types) { + ArrayList result = new ArrayList(); + if (types.length > 0) { + ArrayList argcTypes = new ArrayList(); + // build arity-zero types first + for (Class rtype : types) { + argcTypes.add(MethodType.methodType(rtype)); + } + if (types[0] == void.class) + // void is not an argument type + types = Arrays.copyOfRange(types, 1, types.length); + for (int argc = 0; argc <= maxargc; argc++) { + if (argc >= minargc) + result.addAll(argcTypes); + if (argc >= maxargc) + break; + ArrayList prevTypes = argcTypes; + argcTypes = new ArrayList(); + for (MethodType prevType : prevTypes) { + for (Class ptype : types) { + argcTypes.add(prevType.insertParameterTypes(argc, ptype)); + } + } + } + } + return Collections.unmodifiableList(result); + } + static List allMethodTypes(int argc, Class... types) { + return allMethodTypes(argc, argc, types); + } + + interface RandomInterface { } + + MethodHandle toString_MH; + + @Test + public void testReferenceConversions() throws Throwable { + startTest("testReferenceConversions"); + toString_MH = LOOKUP. + findVirtual(Object.class, "toString", MethodType.methodType(String.class)); + String[] args = { "one", "two" }; + for (MethodType type : allMethodTypes(2, Object.class, String.class, RandomInterface.class)) { + testReferenceConversions(type, args); + } + } + public void testReferenceConversions(MethodType type, Object... args) throws Throwable { + countTest(); + if (verbosity > 3) System.out.println("target type: "+type); + MethodHandle mh = callable(type.parameterList()); + MethodHandle tsdrop = MethodHandles.dropArguments(toString_MH, 1, type.parameterList()); + mh = MethodHandles.foldArguments(tsdrop, mh); + mh = mh.asType(type); + Object res = mh.invokeGeneric((String)args[0], (Object)args[1]); + //System.out.println(res); + assertEquals(Arrays.asList(args).toString(), res); + } + + + @Test @Ignore("known failure pending 6939861") + public void testBoxConversions() throws Throwable { + startTest("testBoxConversions"); + countTest(); + Integer[] args = { 1, 2 }; + MethodHandle mh = callable(Object.class, int.class); + Object res; List resl; + res = resl = (List) mh.invokeGeneric((int)args[0], (Object)args[1]); + //System.out.println(res); + assertEquals(Arrays.asList(args), res); + } + +} diff --git a/jdk/test/java/dyn/MethodHandlesTest.java b/jdk/test/java/dyn/MethodHandlesTest.java index 62b0c903269..6986390c72e 100644 --- a/jdk/test/java/dyn/MethodHandlesTest.java +++ b/jdk/test/java/dyn/MethodHandlesTest.java @@ -1472,7 +1472,7 @@ public class MethodHandlesTest { if (pos != 0) return; // can fold only at pos=0 for now countTest(); MethodHandle target = ValueConversions.varargsList(1 + nargs); - MethodHandle combine = ValueConversions.varargsList(fold); + MethodHandle combine = ValueConversions.varargsList(fold).asType(MethodType.genericMethodType(fold)); List argsToPass = Arrays.asList(randomArgs(nargs, Object.class)); if (verbosity >= 3) System.out.println("fold "+target+" with "+combine); From 4f508abf4971a7bc1f87d0f01f929f153872e9e0 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Sat, 30 Oct 2010 21:08:23 -0700 Subject: [PATCH 007/139] 6981777: implement JSR 292 EG adjustments from summer 2010 Reviewed-by: twisti --- .../classes/java/dyn/BootstrapMethod.java | 82 --- jdk/src/share/classes/java/dyn/CallSite.java | 238 +++--- .../classes/java/dyn/ConstantCallSite.java | 8 +- .../share/classes/java/dyn/InvokeDynamic.java | 80 -- jdk/src/share/classes/java/dyn/Linkage.java | 142 +--- .../classes/java/dyn/LinkagePermission.java | 102 --- .../share/classes/java/dyn/MethodHandle.java | 412 ++++++----- .../java/dyn/MethodHandleProvider.java | 80 -- .../share/classes/java/dyn/MethodHandles.java | 686 +++++++++++------- .../share/classes/java/dyn/MethodType.java | 72 +- .../classes/java/dyn/VolatileCallSite.java | 144 ++++ .../share/classes/java/dyn/package-info.java | 287 +++++--- .../classes/sun/dyn/AdapterMethodHandle.java | 2 +- .../classes/sun/dyn/BoundMethodHandle.java | 24 +- .../share/classes/sun/dyn/CallSiteImpl.java | 48 +- .../share/classes/sun/dyn/FilterGeneric.java | 8 +- .../classes/sun/dyn/FilterOneArgument.java | 4 +- .../share/classes/sun/dyn/FromGeneric.java | 6 +- jdk/src/share/classes/sun/dyn/Invokers.java | 33 + .../classes/sun/dyn/JavaMethodHandle.java | 172 ----- .../classes/sun/dyn/MethodHandleImpl.java | 41 +- .../share/classes/sun/dyn/SpreadGeneric.java | 8 +- jdk/src/share/classes/sun/dyn/ToGeneric.java | 8 +- .../sun/dyn/util/ValueConversions.java | 6 +- .../classes/sun/dyn/util/VerifyAccess.java | 27 +- .../share/classes/sun/dyn/util/Wrapper.java | 91 ++- jdk/test/java/dyn/InvokeGenericTest.java | 2 +- ...Examples.java => JavaDocExamplesTest.java} | 86 ++- jdk/test/java/dyn/MethodHandlesTest.java | 145 ++-- 29 files changed, 1572 insertions(+), 1472 deletions(-) delete mode 100644 jdk/src/share/classes/java/dyn/BootstrapMethod.java delete mode 100644 jdk/src/share/classes/java/dyn/InvokeDynamic.java delete mode 100644 jdk/src/share/classes/java/dyn/LinkagePermission.java delete mode 100644 jdk/src/share/classes/java/dyn/MethodHandleProvider.java create mode 100644 jdk/src/share/classes/java/dyn/VolatileCallSite.java delete mode 100644 jdk/src/share/classes/sun/dyn/JavaMethodHandle.java rename jdk/test/java/dyn/{JavaDocExamples.java => JavaDocExamplesTest.java} (57%) diff --git a/jdk/src/share/classes/java/dyn/BootstrapMethod.java b/jdk/src/share/classes/java/dyn/BootstrapMethod.java deleted file mode 100644 index a5c41b4854b..00000000000 --- a/jdk/src/share/classes/java/dyn/BootstrapMethod.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.dyn; - -import java.lang.annotation.*; - -/** - * Annotation on InvokeDynamic method calls which requests the JVM to use a specific - * bootstrap method - * to link the call. This annotation is not retained as such in the class file, - * but is transformed into a constant-pool entry for the invokedynamic instruction which - * specifies the desired bootstrap method. - *

- * If only the value is given, it must name a subclass of {@link CallSite} - * with a constructor which accepts a class, string, and method type. - * If the value and name are both given, there must be - * a static method in the given class of the given name which accepts a class, string, - * and method type, and returns a reference coercible to {@link CallSite}. - *

- * This annotation can be placed either on the return type of a single {@link InvokeDynamic} - * call (see examples) or else it can be placed on an enclosing class or method, where it - * determines a default bootstrap method for any {@link InvokeDynamic} calls which are not - * specifically annotated with a bootstrap method. - * Every {@link InvokeDynamic} call must be given a bootstrap method. - *

- * Examples: -

-@BootstrapMethod(value=MyLanguageRuntime.class, name="bootstrapDynamic")
-String x = (String) InvokeDynamic.greet();
-//BSM => MyLanguageRuntime.bootstrapDynamic(Here.class, "greet", methodType(String.class))
-@BootstrapMethod(MyCallSite.class)
-void example() throws Throwable {
-    InvokeDynamic.greet();
-    //BSM => new MyCallSite(Here.class, "greet", methodType(void.class))
-}
-
- *

- */ -@Target({ElementType.TYPE_USE, - // For defaulting every indy site within a class or method; cf. @SuppressWarnings: - ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR - }) -@Retention(RetentionPolicy.SOURCE) -public @interface BootstrapMethod { - /** The class containing the bootstrap method. */ - Class value(); - - /** The name of the bootstrap method. - * If this is the empty string, an instance of the bootstrap class is created, - * and a constructor is invoked. - * Otherwise, there must be a static method of the required name. - */ - String name() default ""; // empty string denotes a constructor with 'new' - - /** The argument types of the bootstrap method, as passed out by the JVM. - * There is usually no reason to override the default. - */ - Class[] arguments() default {Class.class, String.class, MethodType.class}; -} diff --git a/jdk/src/share/classes/java/dyn/CallSite.java b/jdk/src/share/classes/java/dyn/CallSite.java index 7c4ed52ea68..7cec9bc290b 100644 --- a/jdk/src/share/classes/java/dyn/CallSite.java +++ b/jdk/src/share/classes/java/dyn/CallSite.java @@ -26,40 +26,34 @@ package java.dyn; import sun.dyn.*; +import sun.dyn.empty.Empty; +import sun.misc.Unsafe; import java.util.Collection; /** * A {@code CallSite} is a holder for a variable {@link MethodHandle}, * which is called its {@code target}. - * Every call to a {@code CallSite} is delegated to the site's current target. + * An {@code invokedynamic} instruction linked to a {@code CallSite} delegates + * all calls to the site's current target. *

- * A call site is initially created in an unlinked state, - * which is distinguished by a null target variable. - * Before the call site may be invoked (and before certain other - * operations are attempted), the call site must be linked to - * a non-null target. + * If a mutable target is not required, the {@code invokedynamic} instruction + * should be linked to a {@linkplain ConstantCallSite constant call site}. + * If a volatile target is required, because updates to the target must be + * reliably witnessed by other threads, the {@code invokedynamic} instruction + * should be linked to a {@linkplain VolatileCallSite volatile call site}. *

* A call site may be relinked by changing its target. - * The new target must be non-null and must have the same - * {@linkplain MethodHandle#type() type} + * The new target must have the same {@linkplain MethodHandle#type() type} * as the previous target. * Thus, though a call site can be relinked to a series of * successive targets, it cannot change its type. *

- * Linkage happens once in the lifetime of any given {@code CallSite} object. - * Because of call site invalidation, this linkage can be repeated for - * a single {@code invokedynamic} instruction, with multiple {@code CallSite} objects. - * When a {@code CallSite} is unlinked from an {@code invokedynamic} instruction, - * the instruction is reset so that it is no longer associated with - * the {@code CallSite} object, but the {@code CallSite} does not change - * state. - *

* Here is a sample use of call sites and bootstrap methods which links every * dynamic call site to print its arguments:


-@BootstrapMethod(value=PrintArgsDemo.class, name="bootstrapDynamic")
 static void test() throws Throwable {
-    InvokeDynamic.baz("baz arg", 2, 3.14);
+    // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION
+    InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14);
 }
 private static void printArgs(Object... args) {
   System.out.println(java.util.Arrays.deepToString(args));
@@ -71,16 +65,14 @@ static {
   printArgs = lookup.findStatic(thisClass,
       "printArgs", MethodType.methodType(void.class, Object[].class));
 }
-private static CallSite bootstrapDynamic(Class caller, String name, MethodType type) {
+private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) {
   // ignore caller and name, but match the type:
-  return new CallSite(MethodHandles.collectArguments(printArgs, type));
+  return new ConstantCallSite(MethodHandles.collectArguments(printArgs, type));
 }
 
* @author John Rose, JSR 292 EG */ -public class CallSite - implements MethodHandleProvider -{ +public class CallSite { private static final Access IMPL_TOKEN = Access.getToken(); // Fields used only by the JVM. Do not use or change. @@ -88,61 +80,44 @@ public class CallSite private int vmindex; // supplied by the JVM (BCI within calling method) // The actual payload of this call site: - private MethodHandle target; + /*package-private*/ + MethodHandle target; // Remove this field for PFD and delete deprecated methods: private MemberName calleeNameRemoveForPFD; /** - * Make a blank call site object. - * Before it is returned from a bootstrap method, this {@code CallSite} object - * must be provided with - * a target method via a call to {@link CallSite#setTarget(MethodHandle) setTarget}, - * or by a subclass override of {@link CallSite#initialTarget(Class,String,MethodType) initialTarget}. + * PROVISIONAL API, WORK IN PROGRESS: + * Make a blank call site object with the given method type. + * An initial target method is supplied which will throw + * an {@link IllegalStateException} if called. + *

+ * Before this {@code CallSite} object is returned from a bootstrap method, + * it is usually provided with a more useful target method, + * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}. */ - public CallSite() { + public CallSite(MethodType type) { + target = MethodHandles.invokers(type).uninitializedCallSite(); } /** * Make a blank call site object, possibly equipped with an initial target method handle. - * The initial target reference may be null, in which case the {@code CallSite} object - * must be provided with a target method via a call to {@link CallSite#setTarget}, - * or by a subclass override of {@link CallSite#initialTarget}. - * @param target the method handle which will be the initial target of the call site, or null if there is none yet + * @param target the method handle which will be the initial target of the call site */ public CallSite(MethodHandle target) { + target.type(); // null check this.target = target; } - /** @deprecated transitional form defined in EDR but removed in PFD */ - public CallSite(Class caller, String name, MethodType type) { - this.calleeNameRemoveForPFD = new MemberName(caller, name, type); - } - /** @deprecated transitional form defined in EDR but removed in PFD */ - public Class callerClass() { - MemberName callee = this.calleeNameRemoveForPFD; - return callee == null ? null : callee.getDeclaringClass(); - } - /** @deprecated transitional form defined in EDR but removed in PFD */ - public String name() { - MemberName callee = this.calleeNameRemoveForPFD; - return callee == null ? null : callee.getName(); - } - /** @deprecated transitional form defined in EDR but removed in PFD */ - public MethodType type() { - MemberName callee = this.calleeNameRemoveForPFD; - return callee == null ? (target == null ? null : target.type()) : callee.getMethodType(); - } - /** @deprecated transitional form defined in EDR but removed in PFD */ - protected MethodHandle initialTarget() { - return initialTarget(callerClass(), name(), type()); - } - - /** Report if the JVM has linked this {@code CallSite} object to a dynamic call site instruction. - * Once it is linked, it is never unlinked. + /** + * Report the type of this call site's target. + * Although targets may change, the call site's type can never change. + * The {@code setTarget} method enforces this invariant by refusing any new target that does + * not have the previous target's type. + * @return the type of the current target, which is also the type of any future target */ - private boolean isLinked() { - return vmmethod != null; + public MethodType type() { + return target.type(); } /** Called from JVM (or low-level Java code) after the BSM returns the newly created CallSite. @@ -152,68 +127,66 @@ public class CallSite MethodType type, MemberName callerMethod, int callerBCI) { - if (this.isLinked()) { + if (this.vmmethod != null) { + // FIXME throw new InvokeDynamicBootstrapError("call site has already been linked to an invokedynamic instruction"); } - MethodHandle target = this.target; - if (target == null) { - this.target = target = this.initialTarget(callerMethod.getDeclaringClass(), name, type); - } - if (!target.type().equals(type)) { + if (!this.type().equals(type)) { throw wrongTargetType(target, type); } this.vmindex = callerBCI; this.vmmethod = callerMethod; - assert(this.isLinked()); } /** - * Just after a call site is created by a bootstrap method handle, - * if the target has not been initialized by the factory method itself, - * the method {@code initialTarget} is called to produce an initial - * non-null target. (Live call sites must never have null targets.) + * Report the current linkage state of the call site, a value which may change over time. *

- * The arguments are the same as those passed to the bootstrap method. - * Thus, a bootstrap method is free to ignore the arguments and simply - * create a "blank" {@code CallSite} object of an appropriate subclass. + * If a {@code CallSite} object is returned + * from the bootstrap method of the {@code invokedynamic} instruction, + * the {@code CallSite} is permanently bound to that instruction. + * When the {@code invokedynamic} instruction is executed, the target method + * of its associated call site object is invoked directly. + * It is as if the instruction calls {@code getTarget} and then + * calls {@link MethodHandle#invokeExact invokeExact} on the result. *

- * If the bootstrap method itself does not initialize the call site, - * this method must be overridden, because it just raises an - * {@code InvokeDynamicBootstrapError}, which in turn causes the - * linkage of the {@code invokedynamic} instruction to terminate - * abnormally. - * @deprecated transitional form defined in EDR but removed in PFD - */ - protected MethodHandle initialTarget(Class callerClass, String name, MethodType type) { - throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+name+type); - } - - /** - * Report the current linkage state of the call site. (This is mutable.) - * The value may not be null after the {@code CallSite} object is returned - * from the bootstrap method of the {@code invokedynamic} instruction. - * When an {@code invokedynamic} instruction is executed, the target method - * of its associated {@code call site} object is invoked directly, - * as if via {@link MethodHandle}{@code .invoke}. - *

- * The interactions of {@code getTarget} with memory are the same + * Unless specified differently by a subclass, + * the interactions of {@code getTarget} with memory are the same * as of a read from an ordinary variable, such as an array element or a * non-volatile, non-final field. *

* In particular, the current thread may choose to reuse the result * of a previous read of the target from memory, and may fail to see * a recent update to the target by another thread. - * @return the current linkage state of the call site + *

+ * In a {@linkplain ConstantCallSite constant call site}, the {@code getTarget} method behaves + * like a read from a {@code final} field of the {@code CallSite}. + *

+ * In a {@linkplain VolatileCallSite volatile call site}, the {@code getTarget} method behaves + * like a read from a {@code volatile} field of the {@code CallSite}. + *

+ * This method may not be overridden by application code. + * @return the current linkage state of the call site, its target method handle + * @see ConstantCallSite + * @see VolatileCallSite * @see #setTarget */ - public MethodHandle getTarget() { + public final MethodHandle getTarget() { + return getTarget0(); + } + + /** + * Privileged implementations can override this to force final or volatile semantics on getTarget. + */ + /*package-private*/ + MethodHandle getTarget0() { return target; } /** * Set the target method of this call site. *

- * The interactions of {@code setTarget} with memory are the same + * Unless a subclass of CallSite documents otherwise, + * the interactions of {@code setTarget} with memory are the same * as of a write to an ordinary variable, such as an array element or a * non-volatile, non-final field. *

@@ -224,27 +197,23 @@ public class CallSite * at any given call site. * @param newTarget the new target * @throws NullPointerException if the proposed new target is null - * @throws WrongMethodTypeException if the call site is linked and the proposed new target + * @throws WrongMethodTypeException if the proposed new target * has a method type that differs from the previous target */ public void setTarget(MethodHandle newTarget) { - MethodType newType = newTarget.type(); // null check! - MethodHandle oldTarget = this.target; - if (oldTarget == null) { - // CallSite is not yet linked. - assert(!isLinked()); - this.target = newTarget; // might be null! - return; - } + checkTargetChange(this.target, newTarget); + setTargetNormal(newTarget); + } + + void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) { MethodType oldType = oldTarget.type(); - if (!newTarget.type().equals(oldType)) + MethodType newType = newTarget.type(); // null check! + if (!newType.equals(oldType)) throw wrongTargetType(newTarget, oldType); - if (oldTarget != newTarget) - CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget); } private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) { - return new WrongMethodTypeException(String.valueOf(target)+target.type()+" should be of type "+type); + return new WrongMethodTypeException(String.valueOf(target)+" should be of type "+type); } /** Produce a printed representation that displays information about this call site @@ -252,15 +221,14 @@ public class CallSite */ @Override public String toString() { - return "CallSite"+(target == null ? "" : target.type()); + return super.toString() + type(); } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle equivalent to an invokedynamic instruction * which has been linked to this call site. - *

If this call site is a {@link ConstantCallSite}, this method - * simply returns the call site's target, since that will not change. + *

If this call site is a {@linkplain ConstantCallSite constant call site}, + * this method simply returns the call site's target, since that will never change. *

Otherwise, this method is equivalent to the following code: *

      * MethodHandle getTarget, invoker, result;
@@ -271,8 +239,9 @@ public class CallSite
      * @return a method handle which always invokes this call site's current target
      */
     public final MethodHandle dynamicInvoker() {
-        if (this instanceof ConstantCallSite)
-            return getTarget();  // will not change dynamically
+        if (this instanceof ConstantCallSite) {
+            return target;  // will not change dynamically
+        }
         MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this);
         MethodHandle invoker = MethodHandles.exactInvoker(this.type());
         return MethodHandles.foldArguments(invoker, getTarget);
@@ -287,9 +256,34 @@ public class CallSite
         }
     }
 
-    /** Implementation of {@link MethodHandleProvider} which returns {@code this.dynamicInvoker()}. */
-    public final MethodHandle asMethodHandle() { return dynamicInvoker(); }
+    /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
+    /*package-private*/
+    static Empty uninitializedCallSite() {
+        throw new IllegalStateException("uninitialized call site");
+    }
 
-    /** Implementation of {@link MethodHandleProvider}, which returns {@code this.dynamicInvoker().asType(type)}. */
-    public final MethodHandle asMethodHandle(MethodType type) { return dynamicInvoker().asType(type); }
+    // unsafe stuff:
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final long TARGET_OFFSET;
+
+    static {
+        try {
+            TARGET_OFFSET = unsafe.objectFieldOffset(CallSite.class.getDeclaredField("target"));
+        } catch (Exception ex) { throw new Error(ex); }
+    }
+
+    /*package-private*/
+    void setTargetNormal(MethodHandle newTarget) {
+        target = newTarget;
+        //CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
+    }
+    /*package-private*/
+    MethodHandle getTargetVolatile() {
+        return (MethodHandle) unsafe.getObjectVolatile(this, TARGET_OFFSET);
+    }
+    /*package-private*/
+    void setTargetVolatile(MethodHandle newTarget) {
+        unsafe.putObjectVolatile(this, TARGET_OFFSET, newTarget);
+        //CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
+    }
 }
diff --git a/jdk/src/share/classes/java/dyn/ConstantCallSite.java b/jdk/src/share/classes/java/dyn/ConstantCallSite.java
index e03fa8d3368..24e623b6c53 100644
--- a/jdk/src/share/classes/java/dyn/ConstantCallSite.java
+++ b/jdk/src/share/classes/java/dyn/ConstantCallSite.java
@@ -27,8 +27,8 @@ package java.dyn;
 
 /**
  * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
- * The only way to relink an {@code invokedynamic} instruction bound to a {@code ConstantCallSite} is
- * to invalidate the instruction as a whole.
+ * An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently
+ * bound to the call site's target.
  * @author John Rose, JSR 292 EG
  */
 public class ConstantCallSite extends CallSite {
@@ -36,7 +36,9 @@ public class ConstantCallSite extends CallSite {
     public ConstantCallSite(MethodHandle target) {
         super(target);
     }
-    /** Throw an {@link IllegalArgumentException}, because this kind of call site cannot change its target. */
+    /**
+     * Throw an {@link IllegalArgumentException}, because this kind of call site cannot change its target.
+     */
     @Override public final void setTarget(MethodHandle ignore) {
         throw new IllegalArgumentException("ConstantCallSite");
     }
diff --git a/jdk/src/share/classes/java/dyn/InvokeDynamic.java b/jdk/src/share/classes/java/dyn/InvokeDynamic.java
deleted file mode 100644
index 4406363a990..00000000000
--- a/jdk/src/share/classes/java/dyn/InvokeDynamic.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * {@code InvokeDynamic} is a class with neither methods nor instances,
- * which serves only as a syntactic marker in Java source code for
- * an {@code invokedynamic} instruction.
- * (See the package information for specifics on this instruction.)
- * 

- * The {@code invokedynamic} instruction is incomplete without a target method. - * The target method is a property of the reified {@linkplain CallSite call site object} - * which is linked to each active {@code invokedynamic} instruction. - * The call site object is initially produced by a - * {@linkplain BootstrapMethod bootstrap method} - * associated with the class whose bytecodes include the dynamic call site. - *

- * The type {@code InvokeDynamic} has no particular meaning as a - * class or interface supertype, or an object type; it can never be instantiated. - * Logically, it denotes a source of all dynamically typed methods. - * It may be viewed as a pure syntactic marker of static calls. - * It may be imported for ease of use. - *

- * Here are some examples: -


-@BootstrapMethod(value=Here.class, name="bootstrapDynamic")
-static void example() throws Throwable {
-    Object x; String s; int i;
-    x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
-    s = (String) InvokeDynamic.hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
-    InvokeDynamic.cogito(); // cogito()V
-    i = (int) InvokeDynamic.#"op:+"(2, 3); // "op:+"(II)I
-}
-static MethodHandle bootstrapDynamic(Class caller, String name, MethodType type) { ... }
-
- * Each of the above calls generates a single invokedynamic instruction - * with the name-and-type descriptors indicated in the comments. - *

- * The argument types are taken directly from the actual arguments, - * while the return type corresponds to the target of the assignment. - * (Currently, the return type must be given as a false type parameter. - * This type parameter is an irregular use of the generic type syntax, - * and is likely to change in favor of a convention based on target typing.) - *

- * The final example uses a special syntax for uttering non-Java names. - * Any name legal to the JVM may be given between the double quotes. - *

- * None of these calls is complete without a bootstrap method, - * which must be declared for the enclosing class or method. - * @author John Rose, JSR 292 EG - */ -@MethodHandle.PolymorphicSignature -public final class InvokeDynamic { - private InvokeDynamic() { throw new InternalError(); } // do not instantiate - - // no statically defined static methods -} diff --git a/jdk/src/share/classes/java/dyn/Linkage.java b/jdk/src/share/classes/java/dyn/Linkage.java index 98eedbbabfb..76abe2430a3 100644 --- a/jdk/src/share/classes/java/dyn/Linkage.java +++ b/jdk/src/share/classes/java/dyn/Linkage.java @@ -29,15 +29,16 @@ import java.dyn.MethodHandles.Lookup; import java.util.WeakHashMap; import sun.dyn.Access; import sun.dyn.MethodHandleImpl; +import sun.dyn.util.VerifyAccess; import sun.reflect.Reflection; -import static sun.dyn.util.VerifyAccess.checkBootstrapPrivilege; import static sun.dyn.MemberName.newIllegalArgumentException; /** - * This class consists exclusively of static methods that control - * the linkage of {@code invokedynamic} instructions, and specifically - * their reification as {@link CallSite} objects. + * CLASS WILL BE REMOVED FOR PFD: + * Static routines for controlling invokedynamic behavior. + * Replaced by non-static APIs. * @author John Rose, JSR 292 EG + * @deprecated This class will be removed in the Public Final Draft. */ public class Linkage { private static final Access IMPL_TOKEN = Access.getToken(); @@ -45,68 +46,24 @@ public class Linkage { private Linkage() {} // do not instantiate /** - * PROVISIONAL API, WORK IN PROGRESS: + * METHOD WILL BE REMOVED FOR PFD: * Register a bootstrap method to use when linking dynamic call sites within * a given caller class. - *

- * A bootstrap method must be a method handle with a return type of {@link CallSite} - * and the following arguments: - *

    - *
  • the class containing the {@code invokedynamic} instruction, for which the bootstrap method was registered - *
  • the name of the method being invoked (a {@link String}) - *
  • the type of the method being invoked (a {@link MethodType}) - *
- * The bootstrap method acts as a factory method which accepts the given arguments - * and returns a {@code CallSite} object (possibly of a subclass of {@code CallSite}). - *

- * The registration must take place exactly once, either before the class has begun - * being initialized, or from within the class's static initializer. - * Registration will fail with an exception if any of the following conditions hold: - *

    - *
  • The immediate caller of this method is in a different package than the given caller class, - * and there is a security manager, and its {@code checkPermission} call throws - * when passed {@link LinkagePermission}("registerBootstrapMethod",callerClass). - *
  • The given caller class already has a bootstrap method registered. - *
  • The given caller class is already fully initialized. - *
  • The given caller class is in the process of initialization, in another thread. - *
- * Because of these rules, a class may install its own bootstrap method in - * a static initializer. - * @param callerClass a class that may have {@code invokedynamic} sites - * @param bootstrapMethod the method to use to bootstrap all such sites - * @exception IllegalArgumentException if the class argument is null or - * a primitive class, or if the bootstrap method is the wrong type - * @exception IllegalStateException if the class already has a bootstrap - * method, or if the its static initializer has already run - * or is already running in another thread - * @exception SecurityException if there is a security manager installed, - * and a {@link LinkagePermission} check fails for "registerBootstrapMethod" - * @deprecated Use @{@link BootstrapMethod} annotations instead + * @deprecated Use @{@link BootstrapMethod} annotations instead. */ public static void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) { Class callc = Reflection.getCallerClass(2); - checkBootstrapPrivilege(callc, callerClass, "registerBootstrapMethod"); - checkBSM(bootstrapMethod); + if (callc != null && !VerifyAccess.isSamePackage(callerClass, callc)) + throw new IllegalArgumentException("cannot set bootstrap method on "+callerClass); MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod); } - static private void checkBSM(MethodHandle mh) { - if (mh == null) throw newIllegalArgumentException("null bootstrap method"); - if (mh.type() == BOOTSTRAP_METHOD_TYPE) return; - throw new WrongMethodTypeException(mh.toString()); - } - /** - * PROVISIONAL API, WORK IN PROGRESS: + * METHOD WILL BE REMOVED FOR PFD: * Simplified version of {@code registerBootstrapMethod} for self-registration, * to be called from a static initializer. - * Finds a static method of the required type in the - * given runtime class, and installs it on the caller class. - * @throws NoSuchMethodException if there is no such method - * @throws IllegalStateException if the caller class's static initializer - * has already run, or is already running in another thread - * @deprecated Use @{@link BootstrapMethod} annotations instead + * @deprecated Use @{@link BootstrapMethod} annotations instead. */ public static void registerBootstrapMethod(Class runtime, String name) { @@ -115,15 +72,9 @@ public class Linkage { } /** - * PROVISIONAL API, WORK IN PROGRESS: + * METHOD WILL BE REMOVED FOR PFD: * Simplified version of {@code registerBootstrapMethod} for self-registration, - * to be called from a static initializer. - * Finds a static method of the required type in the - * caller class itself, and installs it on the caller class. - * @throws IllegalArgumentException if there is no such method - * @throws IllegalStateException if the caller class's static initializer - * has already run, or is already running in another thread - * @deprecated Use @{@link BootstrapMethod} annotations instead + * @deprecated Use @{@link BootstrapMethod} annotations instead. */ public static void registerBootstrapMethod(String name) { @@ -140,82 +91,33 @@ public class Linkage { } catch (NoAccessException ex) { throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex); } - checkBSM(bootstrapMethod); MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod); } - /** - * PROVISIONAL API, WORK IN PROGRESS: - * Report the bootstrap method registered for a given caller class. - * Returns null if the class has never yet registered a bootstrap method. - * Only callers privileged to set the bootstrap method may inquire - * about it, because a bootstrap method is potentially a back-door entry - * point into its class. - * @exception IllegalArgumentException if the argument is null or - * a primitive class - * @exception SecurityException if there is a security manager installed, - * and the immediate caller of this method is not in the same - * package as the caller class - * and a {@link LinkagePermission} check fails for "getBootstrapMethod" - * @deprecated - */ - public static - MethodHandle getBootstrapMethod(Class callerClass) { - Class callc = Reflection.getCallerClass(2); - checkBootstrapPrivilege(callc, callerClass, "getBootstrapMethod"); - return MethodHandleImpl.getBootstrap(IMPL_TOKEN, callerClass); - } - - /** - * PROVISIONAL API, WORK IN PROGRESS: - * The type of any bootstrap method is a three-argument method - * {@code (Class, String, MethodType)} returning a {@code CallSite}. - */ - public static final MethodType BOOTSTRAP_METHOD_TYPE + private static final MethodType BOOTSTRAP_METHOD_TYPE = MethodType.methodType(CallSite.class, Class.class, String.class, MethodType.class); /** - * PROVISIONAL API, WORK IN PROGRESS: + * METHOD WILL BE REMOVED FOR PFD: * Invalidate all invokedynamic call sites everywhere. - *

- * When this method returns, every invokedynamic instruction - * will invoke its bootstrap method on next call. - *

- * It is unspecified whether call sites already known to the Java - * code will continue to be associated with invokedynamic - * instructions. If any call site is still so associated, its - * {@link CallSite#getTarget()} method is guaranteed to return null - * the invalidation operation completes. - *

- * Invalidation operations are likely to be slow. Use them sparingly. + * @deprecated Use {@linkplain CallSite#setTarget call site target setting} + * and {@link VolatileCallSite#invalidateAll call site invalidation} instead. */ public static Object invalidateAll() { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission(new LinkagePermission("invalidateAll")); - } - throw new UnsupportedOperationException("NYI"); + throw new UnsupportedOperationException(); } /** - * PROVISIONAL API, WORK IN PROGRESS: + * METHOD WILL BE REMOVED FOR PFD: * Invalidate all {@code invokedynamic} call sites in the bytecodes * of any methods of the given class. - *

- * When this method returns, every matching invokedynamic - * instruction will invoke its bootstrap method on next call. - *

- * For additional semantics of call site invalidation, - * see {@link #invalidateAll()}. + * @deprecated Use {@linkplain CallSite#setTarget call site target setting} + * and {@link VolatileCallSite#invalidateAll call site invalidation} instead. */ public static Object invalidateCallerClass(Class callerClass) { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission(new LinkagePermission("invalidateAll", callerClass)); - } - throw new UnsupportedOperationException("NYI"); + throw new UnsupportedOperationException(); } } diff --git a/jdk/src/share/classes/java/dyn/LinkagePermission.java b/jdk/src/share/classes/java/dyn/LinkagePermission.java deleted file mode 100644 index 9f1c35e85e0..00000000000 --- a/jdk/src/share/classes/java/dyn/LinkagePermission.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.dyn; - -import java.security.*; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.StringTokenizer; - -/** - * PROVISIONAL API, WORK IN PROGRESS: - * This class is for managing runtime permission checking for - * operations performed by methods in the {@link Linkage} class. - * Like a {@link RuntimePermission}, on which it is modeled, - * a {@code LinkagePermission} contains a target name but - * no actions list; you either have the named permission - * or you don't. - *

- * The following table lists all the possible {@code LinkagePermission} target names, - * and for each provides a description of what the permission allows - * and a discussion of the risks of granting code the permission. - *

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Permission Target NameWhat the Permission AllowsRisks of Allowing this Permission
invalidateAllForce the relinking of invokedynamic call sites everywhere.This could allow an attacker to slow down the system, - * or perhaps expose timing bugs in a dynamic language implementations, - * by forcing redundant relinking operations.
invalidateCallerClass.{class name}Force the relinking of invokedynamic call sites in the given class.See {@code invalidateAll}.
- *

ISSUE: Is this still needed? - * - * @see java.lang.RuntimePermission - * @see java.lang.SecurityManager - * - * @author John Rose, JSR 292 EG - */ - -public final class LinkagePermission extends BasicPermission { - /** - * Create a new LinkagePermission with the given name. - * The name is the symbolic name of the LinkagePermission, such as - * "invalidateCallerClass.*", etc. An asterisk - * may appear at the end of the name, following a ".", or by itself, to - * signify a wildcard match. - * - * @param name the name of the LinkagePermission - */ - public LinkagePermission(String name) { - super(name); - } - - /** - * Create a new LinkagePermission with the given name on the given class. - * Equivalent to {@code LinkagePermission(name+"."+clazz.getName())}. - * - * @param name the name of the LinkagePermission - * @param clazz the class affected by the permission - */ - public LinkagePermission(String name, Class clazz) { - super(name + "." + clazz.getName()); - } -} diff --git a/jdk/src/share/classes/java/dyn/MethodHandle.java b/jdk/src/share/classes/java/dyn/MethodHandle.java index 251d338ce53..1aec36e27b0 100644 --- a/jdk/src/share/classes/java/dyn/MethodHandle.java +++ b/jdk/src/share/classes/java/dyn/MethodHandle.java @@ -37,20 +37,29 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility * A method handle is a typed, directly executable reference to a method, * constructor, field, or similar low-level operation, with optional * transformations of arguments or return values. - * (These transformations include conversion, insertion, deletion, - * substitution. See the methods of this class and of {@link MethodHandles}.) + * These transformations are quite general, and include such patterns as + * {@linkplain #asType conversion}, + * {@linkplain #bindTo insertion}, + * {@linkplain java.dyn.MethodHandles#dropArguments deletion}, + * and {@linkplain java.dyn.MethodHandles#filterArguments substitution}. + *

+ * Note: The super-class of MethodHandle is Object. + * Any other super-class visible in the Reference Implementation + * will be removed before the Proposed Final Draft. + * Also, the final version will not include any public or + * protected constructors. *

* Method handles are strongly typed according to signature. * They are not distinguished by method name or enclosing class. * A method handle must be invoked under a signature which matches - * the method handle's own {@link MethodType method type}. + * the method handle's own {@linkplain MethodType method type}. *

- * Every method handle confesses its type via the {@code type} accessor. + * Every method handle reports its type via the {@link #type type} accessor. * The structure of this type is a series of classes, one of which is * the return type of the method (or {@code void.class} if none). *

* Every method handle appears as an object containing a method named - * {@code invoke}, whose signature exactly matches + * {@link #invokeExact invokeExact}, whose signature exactly matches * the method handle's type. * A Java method call expression, which compiles to an * {@code invokevirtual} instruction, @@ -61,15 +70,29 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility * (The type is specified in the {@code invokevirtual} instruction, * via a {@code CONSTANT_NameAndType} constant pool entry.) * The call looks within the receiver object for a method - * named {@code invoke} of the intended method type. + * named {@code invokeExact} of the intended method type. * The call fails with a {@link WrongMethodTypeException} - * if the method does not exist, even if there is an {@code invoke} + * if the method does not exist, even if there is an {@code invokeExact} * method of a closely similar signature. * As with other kinds * of methods in the JVM, signature matching during method linkage * is exact, and does not allow for language-level implicit conversions * such as {@code String} to {@code Object} or {@code short} to {@code int}. *

+ * Each individual method handle also contains a method named + * {@link #invokeGeneric invokeGeneric}, whose type is the same + * as {@code invokeExact}, and is therefore also reported by + * the {@link #type type} accessor. + * A call to {@code invokeGeneric} works the same as a call to + * {@code invokeExact}, if the signature specified by the caller + * exactly matches the method handle's own type. + * If there is a type mismatch, {@code invokeGeneric} attempts + * to adjust the type of the target method handle + * (as if by a call to {@link #asType asType}) + * to obtain an exactly invokable target. + * This allows a more powerful negotiation of method type + * between caller and callee. + *

* A method handle is an unrestricted capability to call a method. * A method handle can be formed on a non-public method by a class * that has access to that method; the resulting handle can be used @@ -77,31 +100,44 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility * checking is performed when the method handle is created, not * (as in reflection) every time it is called. Handles to non-public * methods, or in non-public classes, should generally be kept secret. - * They should not be passed to untrusted code. + * They should not be passed to untrusted code unless their use from + * the untrusted code would be harmless. *

- * Bytecode in an extended JVM can directly call a method handle's - * {@code invoke} from an {@code invokevirtual} instruction. + * Bytecode in the JVM can directly call a method handle's + * {@code invokeExact} method from an {@code invokevirtual} instruction. * The receiver class type must be {@code MethodHandle} and the method name - * must be {@code invoke}. The signature of the invocation + * must be {@code invokeExact}. The signature of the invocation * (after resolving symbolic type names) must exactly match the method type * of the target method. + * Similarly, bytecode can directly call a method handle's {@code invokeGeneric} + * method. The signature of the invocation (after resolving symbolic type names) + * must either exactly match the method type or be a valid argument to + * the target's {@link #asType asType} method. *

- * Every {@code invoke} method always throws {@link Exception}, + * Every {@code invokeExact} and {@code invokeGeneric} method always + * throws {@link java.lang.Throwable Throwable}, * which is to say that there is no static restriction on what a method handle * can throw. Since the JVM does not distinguish between checked * and unchecked exceptions (other than by their class, of course), * there is no particular effect on bytecode shape from ascribing * checked exceptions to method handle invocations. But in Java source * code, methods which perform method handle calls must either explicitly - * throw {@code Exception}, or else must catch all checked exceptions locally. + * throw {@code java.lang.Throwable Throwable}, or else must catch all + * throwables locally, rethrowing only those which are legal in the context, + * and wrapping ones which are illegal. *

- * Bytecode in an extended JVM can directly obtain a method handle + * Bytecode in the JVM can directly obtain a method handle * for any accessible method from a {@code ldc} instruction * which refers to a {@code CONSTANT_Methodref} or * {@code CONSTANT_InterfaceMethodref} constant pool entry. *

- * All JVMs can also use a reflective API called {@code MethodHandles} + * Java code can also use a reflective API called + * {@link java.dyn.MethodHandles.Lookup MethodHandles.Lookup} * for creating and calling method handles. + * For example, a static method handle can be obtained + * from {@link java.dyn.MethodHandles.Lookup#findStatic Lookup.findStatic}. + * There are also bridge methods from Core Reflection API objects, + * such as {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.ureflect}. *

* A method reference may refer either to a static or non-static method. * In the non-static case, the method handle type includes an explicit @@ -131,7 +167,7 @@ mh = lookup.findVirtual(String.class, "replace", mt); s = mh.<String>invokeExact("daddy",'d','n'); assert(s.equals("nanny")); // weakly typed invocation (using MHs.invoke) -s = (String) mh.invokeVarargs("sappy", 'p', 'v'); +s = (String) mh.invokeWithArguments("sappy", 'p', 'v'); assert(s.equals("savvy")); // mt is {Object[] => List} mt = MethodType.methodType(java.util.List.class, Object[].class); @@ -162,7 +198,7 @@ assert(i == 3); * Java types. *

    *
  1. Method types range over all possible arities, - * from no arguments to an arbitrary number of arguments. + * from no arguments to up to 255 of arguments (a limit imposed by the JVM). * Generics are not variadic, and so cannot represent this.
  2. *
  3. Method types can specify arguments of primitive types, * which Java generic types cannot range over.
  4. @@ -189,7 +225,6 @@ public abstract class MethodHandle // Note: This is an implementation inheritance hack, and will be removed // with a JVM change which moves the required hidden state onto this class. extends MethodHandleImpl - implements MethodHandleProvider { private static Access IMPL_TOKEN = Access.getToken(); @@ -208,7 +243,7 @@ public abstract class MethodHandle /** * Report the type of this method handle. - * Every invocation of this method handle must exactly match this type. + * Every invocation of this method handle via {@code invokeExact} must exactly match this type. * @return the method handle type */ public final MethodType type() { @@ -216,12 +251,16 @@ public abstract class MethodHandle } /** - * The constructor for MethodHandle may only be called by privileged code. - * Subclasses may be in other packages, but must possess - * a token which they obtained from MH with a security check. - * @param token non-null object which proves access permission - * @param type type (permanently assigned) of the new method handle + * CONSTRUCTOR WILL BE REMOVED FOR PFD: + * Temporary constructor in early versions of the Reference Implementation. + * Method handle inheritance (if any) will be contained completely within + * the {@code java.dyn} package. */ + // The constructor for MethodHandle may only be called by privileged code. + // Subclasses may be in other packages, but must possess + // a token which they obtained from MH with a security check. + // @param token non-null object which proves access permission + // @param type type (permanently assigned) of the new method handle protected MethodHandle(Access token, MethodType type) { super(token); Access.check(token); @@ -243,93 +282,104 @@ public abstract class MethodHandle }); } - /** The string of a direct method handle is the simple name of its target method. - * The string of an adapter or bound method handle is the string of its - * target method handle. - * The string of a Java method handle is the string of its entry point method, - * unless the Java method handle overrides the toString method. + /** Produce a printed representation that displays information about this call site + * that may be useful to the human reader. */ @Override public String toString() { return MethodHandleImpl.getNameString(IMPL_TOKEN, this); } - //// This is the "Method Handle Kernel API" discussed at the JVM Language Summit, 9/2009. - //// Implementations here currently delegate to statics in MethodHandles. Some of those statics - //// will be deprecated. Others will be kept as "algorithms" to supply degrees of freedom - //// not present in the Kernel API. - /** - * PROVISIONAL API, WORK IN PROGRESS: * Invoke the method handle, allowing any caller signature, but requiring an exact signature match. * The signature at the call site of {@code invokeExact} must - * exactly match this method handle's {@code type}. + * exactly match this method handle's {@link #type type}. * No conversions are allowed on arguments or return values. + * @throws WrongMethodTypeException if the target's type is not identical with the caller's type signature + * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call */ public final native @PolymorphicSignature R invokeExact(A... args) throws Throwable; - // FIXME: remove this transitional form - /** @deprecated transitional form defined in EDR but removed in PFD */ - public final native @PolymorphicSignature R invoke(A... args) throws Throwable; - /** - * PROVISIONAL API, WORK IN PROGRESS: * Invoke the method handle, allowing any caller signature, - * and performing simple conversions for arguments and return types. - * The signature at the call site of {@code invokeGeneric} must - * have the same arity as this method handle's {@code type}. + * and optionally performing conversions for arguments and return types. *

    - * If the call site signature exactly matches this method handle's {@code type}, - * the call proceeds as if by {@link #invokeExact}. + * If the call site signature exactly matches this method handle's {@link #type type}, + * the call proceeds as if by {@link #invokeExact invokeExact}. *

    * Otherwise, the call proceeds as if this method handle were first - * adjusted by calling {@link #asType} to adjust this method handle + * adjusted by calling {@link #asType asType} to adjust this method handle * to the required type, and then the call proceeds as if by - * {@link #invokeExact} on the adjusted method handle. + * {@link #invokeExact invokeExact} on the adjusted method handle. + *

    + * There is no guarantee that the {@code asType} call is actually made. + * If the JVM can predict the results of making the call, it may perform + * adaptations directly on the caller's arguments, + * and call the target method handle according to its own exact type. + *

    + * If the method handle is equipped with a + * {@linkplain #withTypeHandler type handler}, the handler must produce + * an entry point of the call site's exact type. + * Otherwise, the signature at the call site of {@code invokeGeneric} must + * be a valid argument to the standard {@code asType} method. + * In particular, the caller must specify the same argument arity + * as the callee's type. + * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type signature + * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call */ public final native @PolymorphicSignature R invokeGeneric(A... args) throws Throwable; - // ?? public final native @PolymorphicSignature R invokeVarargs(A args, V[] varargs) throws Throwable; - /** - * PROVISIONAL API, WORK IN PROGRESS: * Perform a varargs invocation, passing the arguments in the given array - * to the method handle, as if via {@link #invokeGeneric} from a call site + * to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site * which mentions only the type {@code Object}, and whose arity is the length * of the argument array. *

    - * The length of the arguments array must equal the parameter count - * of the target's type. - * The arguments array is spread into separate arguments. + * Specifically, execution proceeds as if by the following steps, + * although the methods are not guaranteed to be called if the JVM + * can predict their effects. + *

      + *
    • Determine the length of the argument array as {@code N}. + * For a null reference, {@code N=0}.
    • + *
    • Determine the generic type {@code TN} of {@code N} arguments as + * as {@code TN=MethodType.genericMethodType(N)}.
    • + *
    • Force the original target method handle {@code MH0} to the + * required type, as {@code MH1 = MH0.asType(TN)}.
    • + *
    • Spread the array into {@code N} separate arguments {@code A0, ...}.
    • + *
    • Invoke the type-adjusted method handle on the unpacked arguments: + * MH1.invokeExact(A0, ...).
    • + *
    • Take the return value as an {@code Object} reference.
    • + *
    *

    - * In order to match the type of the target, the following argument + * Because of the action of the {@code asType} step, the following argument * conversions are applied as necessary: *

      *
    • reference casting *
    • unboxing + *
    • widening primitive conversions *
    - * The following conversions are not applied: - *
      - *
    • primitive conversions (e.g., {@code byte} to {@code int} - *
    • varargs conversions other than the initial spread - *
    • any application-specific conversions (e.g., string to number) - *
    + *

    * The result returned by the call is boxed if it is a primitive, * or forced to null if the return type is void. *

    * This call is equivalent to the following code: *

    -     *   MethodHandle invoker = MethodHandles.genericInvoker(this.type(), 0, true);
    -     *   Object result = invoker.invokeExact(this, arguments);
    +     * MethodHandle invoker = MethodHandles.varargsInvoker(this.type(), 0);
    +     * Object result = invoker.invokeExact(this, arguments);
          * 
    * @param arguments the arguments to pass to the target * @return the result returned by the target - * @see MethodHandles#genericInvoker + * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the arguments + * @throws Throwable anything thrown by the target method invocation + * @see MethodHandles#varargsInvoker */ - public final Object invokeVarargs(Object... arguments) throws Throwable { + public final Object invokeWithArguments(Object... arguments) throws Throwable { int argc = arguments == null ? 0 : arguments.length; MethodType type = type(); - if (type.parameterCount() != argc) throw badParameterCount(type, argc); + if (type.parameterCount() != argc) { + // simulate invokeGeneric + return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments); + } if (argc <= 10) { MethodHandle invoker = MethodHandles.invokers(type).genericInvoker(); switch (argc) { @@ -373,82 +423,48 @@ public abstract class MethodHandle MethodHandle invoker = MethodHandles.invokers(type).varargsInvoker(0); return invoker.invokeExact(this, arguments); } - /** Equivalent to {@code invokeVarargs(arguments.toArray())}. */ + /** Equivalent to {@code invokeWithArguments(arguments.toArray())}. */ + public final Object invokeWithArguments(java.util.List arguments) throws Throwable { + return invokeWithArguments(arguments.toArray()); + } + @Deprecated + public final Object invokeVarargs(Object... arguments) throws Throwable { + return invokeWithArguments(arguments); + } + @Deprecated public final Object invokeVarargs(java.util.List arguments) throws Throwable { - return invokeVarargs(arguments.toArray()); + return invokeWithArguments(arguments.toArray()); } - private static WrongMethodTypeException badParameterCount(MethodType type, int argc) { - return new WrongMethodTypeException(type+" does not take "+argc+" parameters"); - } - - /* --- this is intentionally NOT a javadoc yet --- - * PROVISIONAL API, WORK IN PROGRESS: - * Produce an adapter method handle which adapts the type of the - * current method handle to a new type by pairwise argument conversion. - * The original type and new type must have the same number of arguments. - * The resulting method handle is guaranteed to confess a type - * which is equal to the desired new type. - *

    - * If the original type and new type are equal, returns {@code this}. - *

    - * The following conversions are applied as needed both to - * arguments and return types. Let T0 and T1 be the differing - * new and old parameter types (or old and new return types) - * for corresponding values passed by the new and old method types. - * Given those types T0, T1, one of the following conversions is applied - * if possible: - *

      - *
    • If T0 and T1 are references, and T1 is not an interface type, - * then a cast to T1 is applied. - * (The types do not need to be related in any particular way.) - *
    • If T0 and T1 are references, and T1 is an interface type, - * then the value of type T0 is passed as a T1 without a cast. - * (This treatment of interfaces follows the usage of the bytecode verifier.) - *
    • If T0 and T1 are primitives, then a Java casting - * conversion (JLS 5.5) is applied, if one exists. - *
    • If T0 and T1 are primitives and one is boolean, - * the boolean is treated as a one-bit unsigned integer. - * (This treatment follows the usage of the bytecode verifier.) - * A conversion from another primitive type behaves as if - * it first converts to byte, and then masks all but the low bit. - *
    • If T0 is a primitive and T1 a reference, a boxing - * conversion is applied if one exists, possibly followed by - * an reference conversion to a superclass. - * T1 must be a wrapper class or a supertype of one. - * If T1 is a wrapper class, T0 is converted if necessary - * to T1's primitive type by one of the preceding conversions. - * Otherwise, T0 is boxed, and its wrapper converted to T1. - *
    • If T0 is a reference and T1 a primitive, an unboxing - * conversion is applied if one exists, possibly preceded by - * a reference conversion to a wrapper class. - * T0 must be a wrapper class or a supertype of one. - * If T0 is a wrapper class, its primitive value is converted - * if necessary to T1 by one of the preceding conversions. - * Otherwise, T0 is converted directly to the wrapper type for T1, - * which is then unboxed. - *
    • If the return type T1 is void, any returned value is discarded - *
    • If the return type T0 is void and T1 a reference, a null value is introduced. - *
    • If the return type T0 is void and T1 a primitive, a zero value is introduced. - *
    - *

    - */ /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce an adapter method handle which adapts the type of the - * current method handle to a new type by pairwise argument conversion. - * The original type and new type must have the same number of arguments. - * The resulting method handle is guaranteed to confess a type + * current method handle to a new type + * The resulting method handle is guaranteed to report a type * which is equal to the desired new type. *

    * If the original type and new type are equal, returns {@code this}. *

    - * This method is equivalent to {@link MethodHandles#convertArguments}. + * This method provides the crucial behavioral difference between + * {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}. The two methods + * perform the same steps when the caller's type descriptor is identical + * with the callee's, but when the types differ, {@link #invokeGeneric invokeGeneric} + * also calls {@code asType} (or some internal equivalent) in order + * to match up the caller's and callee's types. + *

    + * This method is equivalent to {@link MethodHandles#convertArguments convertArguments}, + * except for method handles produced by {@link #withTypeHandler withTypeHandler}, + * in which case the specified type handler is used for calls to {@code asType}. + *

    + * Note that the default behavior of {@code asType} only performs + * pairwise argument conversion and return value conversion. + * Because of this, unless the method handle has a type handler, + * the original type and new type must have the same number of arguments. + * * @param newType the expected type of the new method handle * @return a method handle which delegates to {@code this} after performing * any necessary argument conversions, and arranges for any * necessary return value conversions - * @throws IllegalArgumentException if the conversion cannot be made + * @throws WrongMethodTypeException if the conversion cannot be made * @see MethodHandles#convertArguments */ public MethodHandle asType(MethodType newType) { @@ -456,20 +472,21 @@ public abstract class MethodHandle } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle which adapts, as its target, * the current method handle. The type of the adapter will be - * the same as the type of the target, except that all but the first - * {@code keepPosArgs} parameters of the target's type are replaced - * by a single array parameter of type {@code Object[]}. - * Thus, if {@code keepPosArgs} is zero, the adapter will take all - * arguments in a single object array. + * the same as the type of the target, except that the final + * {@code arrayLength} parameters of the target's type are replaced + * by a single array parameter of type {@code arrayType}. + *

    + * If the array element type differs from any of the corresponding + * argument types on original target, + * the original target is adapted to take the array elements directly, + * as if by a call to {@link #asType asType}. *

    * When called, the adapter replaces a trailing array argument * by the array's elements, each as its own argument to the target. * (The order of the arguments is preserved.) * They are converted pairwise by casting and/or unboxing - * (as if by {@link MethodHandles#convertArguments}) * to the types of the trailing parameters of the target. * Finally the target is called. * What the target eventually returns is returned unchanged by the adapter. @@ -478,54 +495,67 @@ public abstract class MethodHandle * contains exactly enough elements to provide a correct argument count * to the target method handle. * (The array may also be null when zero elements are required.) - * @param keepPosArgs the number of leading positional arguments to preserve - * @return a new method handle which spreads its final argument, + * @param arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments + * @param arrayLength the number of arguments to spread from an incoming array argument + * @return a new method handle which spreads its final array argument, * before calling the original method handle + * @throws IllegalArgumentException if {@code arrayType} is not an array type * @throws IllegalArgumentException if target does not have at least - * {@code keepPosArgs} parameter types + * {@code arrayLength} parameter types + * @throws WrongMethodTypeException if the implied {@code asType} call fails */ - public final MethodHandle asSpreader(int keepPosArgs) { + public final MethodHandle asSpreader(Class arrayType, int arrayLength) { + Class arrayElement = arrayType.getComponentType(); + if (arrayElement == null) throw newIllegalArgumentException("not an array type"); MethodType oldType = type(); int nargs = oldType.parameterCount(); + if (nargs < arrayLength) throw newIllegalArgumentException("bad spread array length"); + int keepPosArgs = nargs - arrayLength; MethodType newType = oldType.dropParameterTypes(keepPosArgs, nargs); - newType = newType.insertParameterTypes(keepPosArgs, Object[].class); + newType = newType.insertParameterTypes(keepPosArgs, arrayElement); return MethodHandles.spreadArguments(this, newType); } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle which adapts, as its target, * the current method handle. The type of the adapter will be * the same as the type of the target, except that a single trailing - * array parameter of type {@code Object[]} is replaced by - * {@code spreadArrayArgs} parameters of type {@code Object}. + * parameter (usually of type {@code arrayType}) is replaced by + * {@code arrayLength} parameters whose type is element type of {@code arrayType}. *

    - * When called, the adapter replaces its trailing {@code spreadArrayArgs} - * arguments by a single new {@code Object} array, whose elements + * If the array type differs from the final argument type on original target, + * the original target is adapted to take the array type directly, + * as if by a call to {@link #asType asType}. + *

    + * When called, the adapter replaces its trailing {@code arrayLength} + * arguments by a single new array of type {@code arrayType}, whose elements * comprise (in order) the replaced arguments. * Finally the target is called. * What the target eventually returns is returned unchanged by the adapter. *

    - * (The array may also be a shared constant when {@code spreadArrayArgs} is zero.) - * @param spreadArrayArgs the number of arguments to spread from the trailing array + * (The array may also be a shared constant when {@code arrayLength} is zero.) + * @param arrayType usually {@code Object[]}, the type of the array argument which will collect the arguments + * @param arrayLength the number of arguments to collect into a new array argument * @return a new method handle which collects some trailing argument * into an array, before calling the original method handle - * @throws IllegalArgumentException if the last argument of the target - * is not {@code Object[]} - * @throws IllegalArgumentException if {@code spreadArrayArgs} is not + * @throws IllegalArgumentException if {@code arrayType} is not an array type + or {@code arrayType} is not assignable to this method handle's trailing parameter type + * @throws IllegalArgumentException if {@code arrayLength} is not * a legal array size - * @deprecated Provisional and unstable; use {@link MethodHandles#collectArguments}. + * @throws WrongMethodTypeException if the implied {@code asType} call fails */ - public final MethodHandle asCollector(int spreadArrayArgs) { + public final MethodHandle asCollector(Class arrayType, int arrayLength) { + Class arrayElement = arrayType.getComponentType(); + if (arrayElement == null) throw newIllegalArgumentException("not an array type"); MethodType oldType = type(); int nargs = oldType.parameterCount(); MethodType newType = oldType.dropParameterTypes(nargs-1, nargs); - newType = newType.insertParameterTypes(nargs-1, MethodType.genericMethodType(spreadArrayArgs).parameterArray()); + newType = newType.insertParameterTypes(nargs-1, + java.util.Collections.>nCopies(arrayLength, arrayElement)); return MethodHandles.collectArguments(this, newType); } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle which binds the given argument * to the current method handle as target. * The type of the bound handle will be @@ -546,15 +576,73 @@ public abstract class MethodHandle * leading parameter type that is a reference type * @throws ClassCastException if {@code x} cannot be converted * to the leading parameter type of the target - * @deprecated Provisional and unstable; use {@link MethodHandles#insertArguments}. + * @see MethodHandles#insertArguments */ public final MethodHandle bindTo(Object x) { return MethodHandles.insertArguments(this, 0, x); } - /** Implementation of {@link MethodHandleProvider}, which returns {@code this}. */ - public final MethodHandle asMethodHandle() { return this; } - - /** Implementation of {@link MethodHandleProvider}, which returns {@code this.asType(type)}. */ - public final MethodHandle asMethodHandle(MethodType type) { return this.asType(type); } + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Create a new method handle with the same type as this one, + * but whose {@code asType} method invokes the given + * {@code typeHandler} on this method handle, + * instead of the standard {@code MethodHandles.convertArguments}. + *

    + * The new method handle will have the same behavior as the + * old one when invoked by {@code invokeExact}. + * For {@code invokeGeneric} calls which exactly match + * the method type, the two method handles will also + * have the same behavior. + * For other {@code invokeGeneric} calls, the {@code typeHandler} + * will control the behavior of the new method handle. + *

    + * Thus, a method handle with an {@code asType} handler can + * be configured to accept more than one arity of {@code invokeGeneric} + * call, and potentially every possible arity. + * It can also be configured to supply default values for + * optional arguments, when the caller does not specify them. + *

    + * The given method handle must take two arguments and return + * one result. The result it returns must be a method handle + * of exactly the requested type. If the result returned by + * the target is null, a {@link NullPointerException} is thrown, + * else if the type of the target does not exactly match + * the requested type, a {@link WrongMethodTypeException} is thrown. + *

    + * Therefore, the type handler is invoked as if by this code: + *

    +     * MethodHandle target = this;      // original method handle
    +     * MethodHandle adapter = ...;      // adapted method handle
    +     * MethodType requestedType = ...;  // argument to asType()
    +     * if (type().equals(requestedType))
    +     *    return adapter;
    +     * MethodHandle result = (MethodHandle)
    +     *    typeHandler.invokeGeneric(target, requestedType);
    +     * if (!result.type().equals(requestedType))
    +     *    throw new WrongMethodTypeException();
    +     * return result;
    +     * 
    + *

    + * For example, here is a list-making variable-arity method handle: + *

    +MethodHandle makeEmptyList = MethodHandles.constant(List.class, Arrays.asList());
    +MethodHandle asList = lookup()
    +  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class));
    +static MethodHandle collectingTypeHandler(MethodHandle base, MethodType newType) {
    +  return asList.asCollector(Object[].class, newType.parameterCount()).asType(newType);
    +}
    +MethodHandle collectingTypeHandler = lookup()
    +  .findStatic(lookup().lookupClass(), "collectingTypeHandler",
    +     methodType(MethodHandle.class, MethodHandle.class, MethodType.class));
    +MethodHandle makeAnyList = makeEmptyList.withTypeHandler(collectingTypeHandler);
    +
    +System.out.println(makeAnyList.invokeGeneric()); // prints []
    +System.out.println(makeAnyList.invokeGeneric(1)); // prints [1]
    +System.out.println(makeAnyList.invokeGeneric("two", "too")); // prints [two, too]
    +     * 
    + */ + public MethodHandle withTypeHandler(MethodHandle typeHandler) { + return MethodHandles.withTypeHandler(this, typeHandler); + } } diff --git a/jdk/src/share/classes/java/dyn/MethodHandleProvider.java b/jdk/src/share/classes/java/dyn/MethodHandleProvider.java deleted file mode 100644 index 365b605469e..00000000000 --- a/jdk/src/share/classes/java/dyn/MethodHandleProvider.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.dyn; - -/** - * An interface for an object to provide a target {@linkplain MethodHandle method handle} to a {@code invokedynamic} instruction. - * There are many function-like objects in various Java APIs. - * This interface provides a standard way for such function-like objects to be bound - * to a dynamic call site, by providing a view of their behavior in the form of a low-level method handle. - *

    - * The type {@link MethodHandle} is a concrete class whose implementation - * hierarchy (if any) may be tightly coupled to the underlying JVM implementation. - * It cannot also serve as a base type for user-defined functional APIs. - * For this reason, {@code MethodHandle} cannot be subclassed to add new - * behavior to method handles. But this interface can be used to provide - * a link between a user-defined function and the {@code invokedynamic} - * instruction and the method handle API. - */ -public interface MethodHandleProvider { - /** Produce a method handle which will serve as a behavioral proxy for the current object. - * The type and invocation behavior of the proxy method handle are user-defined, - * and should have some relation to the intended meaning of the original object itself. - *

    - * The current object may have a changeable behavior. - * For example, {@link CallSite} has a {@code setTarget} method which changes its invocation. - * In such a case, it is incorrect for {@code asMethodHandle} to return - * a method handle whose behavior may diverge from that of the current object. - * Rather, the returned method handle must stably and permanently access - * the behavior of the current object, even if that behavior is changeable. - *

    - * The reference identity of the proxy method handle is not guaranteed to - * have any particular relation to the reference identity of the object. - * In particular, several objects with the same intended meaning could - * share a common method handle, or the same object could return different - * method handles at different times. In the latter case, the different - * method handles should have the same type and invocation behavior, - * and be usable from any thread at any time. - * In particular, if a MethodHandleProvider is bound to an invokedynamic - * call site, the proxy method handle extracted at the time of binding - * will be used for an unlimited time, until the call site is rebound. - *

    - * The type {@link MethodHandle} itself implements {@code MethodHandleProvider}, and - * for this method simply returns {@code this}. - */ - public MethodHandle asMethodHandle(); - - /** Produce a method handle of a given type which will serve as a behavioral proxy for the current object. - * As for the no-argument version {@link #asMethodHandle()}, the invocation behavior of the - * proxy method handle is user-defined. But the type must be the given type, - * or else a {@link WrongMethodTypeException} must be thrown. - *

    - * If the current object somehow represents a variadic or overloaded behavior, - * the method handle returned for a given type might represent only a subset of - * the current object's repertoire of behaviors, which correspond to that type. - */ - public MethodHandle asMethodHandle(MethodType type) throws WrongMethodTypeException; -} diff --git a/jdk/src/share/classes/java/dyn/MethodHandles.java b/jdk/src/share/classes/java/dyn/MethodHandles.java index 3e1fef7ff14..e7a9cd31b23 100644 --- a/jdk/src/share/classes/java/dyn/MethodHandles.java +++ b/jdk/src/share/classes/java/dyn/MethodHandles.java @@ -29,6 +29,7 @@ import java.lang.reflect.*; import sun.dyn.Access; import sun.dyn.MemberName; import sun.dyn.MethodHandleImpl; +import sun.dyn.util.ValueConversions; import sun.dyn.util.VerifyAccess; import sun.dyn.util.Wrapper; import java.util.List; @@ -135,12 +136,19 @@ public class MethodHandles { * In general, the conditions under which a method handle may be * created for a method {@code M} are exactly as restrictive as the conditions * under which the lookup class could have compiled a call to {@code M}. - * This rule is applied even if the Java compiler might have created + *

    + * In some cases, this access is obtained by the Java compiler by creating * an wrapper method to access a private method of another class * in the same top-level declaration. - * For example, a lookup object created for a nested class {@code C.D} + * For example, a nested class {@code C.D} * can access private members within other related classes such as - * {@code C}, {@code C.D.E}, or {@code C.B}. + * {@code C}, {@code C.D.E}, or {@code C.B}, + * but the Java compiler may need to generate wrapper methods in + * those related classes. In such cases, a {@code Lookup} object on + * {@code C.E} would be unable to those private members. + * A workaround for this limitation is the {@link Lookup#in Lookup.in} method, + * which can transform a lookup on {@code C.E} into one on any of those other + * classes, without special elevation of privilege. */ public static final class Lookup { @@ -181,13 +189,23 @@ public class MethodHandles { } /** Which types of members can this lookup object produce? - * The result is a bit-mask of the {@link Modifier} bits - * {@linkplain Modifier#PUBLIC PUBLIC (0x01)}, - * {@linkplain Modifier#PROTECTED PROTECTED (0x02)}, - * {@linkplain Modifier#PRIVATE PRIVATE (0x04)}, - * and {@linkplain Modifier#STATIC STATIC (0x08)}. + * The result is a bit-mask of the {@link java.lang.reflect.Modifier Modifier} bits + * {@linkplain java.lang.reflect.Modifier#PUBLIC PUBLIC (0x01)}, + * {@linkplain java.lang.reflect.Modifier#PROTECTED PROTECTED (0x02)}, + * {@linkplain java.lang.reflect.Modifier#PRIVATE PRIVATE (0x04)}, + * and {@linkplain java.lang.reflect.Modifier#STATIC STATIC (0x08)}. * The modifier bit {@code STATIC} stands in for the package protection mode, * which does not have an explicit modifier bit. + *

    + * A freshly-created lookup object + * on the {@linkplain java.dyn.MethodHandles#lookup() caller's class} + * has all possible bits set, since the caller class can access all its own members. + * A lookup object on a new lookup class + * {@linkplain java.dyn.MethodHandles.Lookup#in created from a previous lookup object} + * may have some mode bits set to zero. + * The purpose of this is to restrict access via the new lookup object, + * so that it can access only names which can be reached by the original + * lookup object, and also by the new lookup class. */ public int lookupModes() { return allowedModes & ALL_MODES; @@ -224,14 +242,17 @@ public class MethodHandles { *

    * However, the resulting {@code Lookup} object is guaranteed * to have no more access capabilities than the original. - * In particular:

      + * In particular, access capabilities can be lost as follows:
        *
      • If the new lookup class differs from the old one, * protected members will not be accessible by virtue of inheritance. + * (Protected members may continue to be accessible because of package sharing.) *
      • If the new lookup class is in a different package * than the old one, protected and default (package) members will not be accessible. *
      • If the new lookup class is not within the same package member * as the old one, private members will not be accessible. - *
      • In all cases, public members will continue to be accessible. + *
      • If the new lookup class is not accessible to the old lookup class, + * then no members, not even public members, will be accessible. + * (In all other cases, public members will continue to be accessible.) *
      */ public Lookup in(Class requestedLookupClass) { @@ -245,10 +266,17 @@ public class MethodHandles { && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) { newModes &= ~(PACKAGE|PRIVATE); } + // Allow nestmate lookups to be created without special privilege: if ((newModes & PRIVATE) != 0 && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) { newModes &= ~PRIVATE; } + if (newModes == PUBLIC + && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass)) { + // The requested class it not accessible from the lookup class. + // No permissions. + newModes = 0; + } checkUnprivilegedlookupClass(requestedLookupClass); return new Lookup(requestedLookupClass, newModes); } @@ -290,8 +318,8 @@ public class MethodHandles { break; case PUBLIC|PACKAGE: return cname + "/package"; - case 0: // should not happen - return cname + "/empty"; + case 0: // no privileges + return cname + "/noaccess"; case ALL_MODES: return cname; } @@ -326,7 +354,6 @@ public class MethodHandles { * @param name the name of the method * @param type the type of the method * @return the desired method handle - * @exception SecurityException TBD * @exception NoAccessException if the method does not exist or access checking fails */ public @@ -358,7 +385,6 @@ public class MethodHandles { * @param name the name of the method * @param type the type of the method, with the receiver argument omitted * @return the desired method handle - * @exception SecurityException TBD * @exception NoAccessException if the method does not exist or access checking fails */ public MethodHandle findVirtual(Class refc, String name, MethodType type) throws NoAccessException { @@ -382,7 +408,6 @@ public class MethodHandles { * @param refc the class or interface from which the method is accessed * @param type the type of the method, with the receiver argument omitted, and a void return type * @return the desired method handle - * @exception SecurityException TBD * @exception NoAccessException if the method does not exist or access checking fails */ public MethodHandle findConstructor(Class refc, MethodType type) throws NoAccessException { @@ -409,13 +434,13 @@ public class MethodHandles { * {@code invokespecial} instruction.) *

      * If the explicitly specified caller class is not identical with the - * lookup class, a security check TBD is performed. + * lookup class, or if this lookup object does not have private access + * privileges, the access fails. * @param refc the class or interface from which the method is accessed * @param name the name of the method (which must not be "<init>") * @param type the type of the method, with the receiver argument omitted * @param specialCaller the proposed calling class to perform the {@code invokespecial} * @return the desired method handle - * @exception SecurityException TBD * @exception NoAccessException if the method does not exist or access checking fails */ public MethodHandle findSpecial(Class refc, String name, MethodType type, @@ -428,7 +453,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle giving read access to a non-static field. * The type of the method handle will have a return type of the field's * value type. @@ -445,7 +469,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle giving write access to a non-static field. * The type of the method handle will have a void return type. * The method handle will take two arguments, the instance containing @@ -462,7 +485,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle giving read access to a static field. * The type of the method handle will have a return type of the field's * value type. @@ -478,7 +500,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle giving write access to a static field. * The type of the method handle will have a void return type. * The method handle will take a single @@ -515,7 +536,6 @@ public class MethodHandles { * @param name the name of the method * @param type the type of the method, with the receiver argument omitted * @return the desired method handle - * @exception SecurityException TBD * @exception NoAccessException if the method does not exist or access checking fails */ public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException { @@ -530,7 +550,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Make a direct method handle to m, if the lookup class has permission. * If m is non-static, the receiver argument is treated as an initial argument. * If m is virtual, overriding is respected on every call. @@ -554,7 +573,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle for a reflected method. * It will bypass checks for overriding methods on the receiver, * as if by a {@code invokespecial} instruction from within the {@code specialCaller}. @@ -579,7 +597,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle for a reflected constructor. * The type of the method handle will be that of the constructor, * with the return type changed to the declaring class. @@ -602,7 +619,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle giving read access to a reflected field. * The type of the method handle will have a return type of the field's * value type. @@ -620,7 +636,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle giving write access to a reflected field. * The type of the method handle will have a void return type. * If the field is static, the method handle will take a single @@ -681,7 +696,7 @@ public class MethodHandles { int allowedModes = this.allowedModes; if (allowedModes == TRUSTED) return; int mods = m.getModifiers(); - if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers())) + if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0) return; // common case int requestedModes = fixmods(mods); // adjust 0 => PACKAGE if ((requestedModes & allowedModes) != 0 @@ -706,6 +721,8 @@ public class MethodHandles { return "access to public member failed"; // (how?) else if (allowedModes == PUBLIC) return "member is not public"; + else if (allowedModes == 0) + return "attempted member access through a non-public class"; if (Modifier.isPrivate(mods)) return "member is private"; if (Modifier.isProtected(mods)) @@ -713,9 +730,14 @@ public class MethodHandles { return "member is private to package"; } + private static final boolean ALLOW_NESTMATE_ACCESS = false; + void checkSpecialCaller(Class specialCaller) throws NoAccessException { if (allowedModes == TRUSTED) return; - if (!VerifyAccess.isSamePackageMember(specialCaller, lookupClass())) + if ((allowedModes & PRIVATE) == 0 + || (specialCaller != lookupClass() + && !(ALLOW_NESTMATE_ACCESS && + VerifyAccess.isSamePackageMember(specialCaller, lookupClass())))) throw newNoAccessException("no private access for invokespecial", new MemberName(specialCaller), lookupClass()); } @@ -725,7 +747,9 @@ public class MethodHandles { // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc. if (!method.isProtected() || method.isStatic() || allowedModes == TRUSTED - || VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())) + || method.getDeclaringClass() == lookupClass() + || (ALLOW_NESTMATE_ACCESS && + VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass()))) return mh; else return restrictReceiver(method, mh, lookupClass()); @@ -765,7 +789,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle giving read access to elements of an array. * The type of the method handle will have a return type of the array's * element type. Its first argument will be the array type, @@ -780,7 +803,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle giving write access to elements of an array. * The type of the method handle will have a void return type. * Its last argument will be the array's element type. @@ -796,25 +818,6 @@ public class MethodHandles { /// method handle invocation (reflective style) /** - * @deprecated Alias for MethodHandle.invokeVarargs. - */ - @Deprecated - public static - Object invokeVarargs(MethodHandle target, Object... arguments) throws Throwable { - return target.invokeVarargs(arguments); - } - - /** - * @deprecated Alias for MethodHandle.invokeVarargs. - */ - @Deprecated - public static - Object invoke(MethodHandle target, Object... arguments) throws Throwable { - return target.invokeVarargs(arguments); - } - - /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle which will invoke any method handle of the * given type on a standard set of {@code Object} type arguments. * The resulting invoker will be a method handle with the following @@ -823,18 +826,28 @@ public class MethodHandles { *

    • a single {@code MethodHandle} target *
    • zero or more {@code Object} values (one for each argument in {@code type}) *
    - * The invoker will apply reference casts as necessary and unbox primitive arguments, - * as if by {@link #convertArguments}. + *

    + * The invoker will behave like a call to {@link MethodHandle.invokeGeneric} with + * the indicated {@code type}. + * That is, if the target is exactly of the given {@code type}, it will behave + * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle.asType} + * is used to convert the target to the required {@code type}. + *

    + * The type of the returned invoker will not be the given {@code type}, but rather + * will have all parameter and return types replaced by {@code Object}. + *

    + * Before invoking its target, the invoker will apply reference casts as + * necessary and unbox and widen primitive arguments, as if by {@link #convertArguments}. * The return value of the invoker will be an {@code Object} reference, * boxing a primitive value if the original type returns a primitive, * and always null if the original type returns void. *

    * This method is equivalent to the following code (though it may be more efficient): *

    -     * MethodHandle invoker = exactInvoker(type);
    +     * MethodHandle invoker = lookup().findVirtual(MethodHandle.class, "invokeGeneric", type);
          * MethodType genericType = type.generic();
          * genericType = genericType.insertParameterType(0, MethodHandle.class);
    -     * return convertArguments(invoker, genericType);
    +     * return invoker.asType(genericType);
          * 
    * @param type the type of target methods which the invoker will apply to * @return a method handle suitable for invoking any method handle of the given type @@ -845,9 +858,8 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle which will invoke any method handle of the - * given type on a standard set of {@code Object} type arguments + * given {@code type} on a standard set of {@code Object} type arguments * and a single trailing {@code Object[]} array. * The resulting invoker will be a method handle with the following * arguments: @@ -856,18 +868,31 @@ public class MethodHandles { *
  5. zero or more {@code Object} values (counted by {@code objectArgCount}) *
  6. an {@code Object[]} array containing more arguments * - * The invoker will spread the varargs array, apply - * reference casts as necessary, and unbox primitive arguments. + *

    + * The invoker will behave like a call to {@link MethodHandle.invokeGeneric} with + * the indicated {@code type}. + * That is, if the target is exactly of the given {@code type}, it will behave + * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle.asType} + * is used to convert the target to the required {@code type}. + *

    + * The type of the returned invoker will not be the given {@code type}, but rather + * will have all parameter and return types replaced by {@code Object}, except for + * the last parameter type, which will be the array type {@code Object[]}. + *

    + * Before invoking its target, the invoker will spread the varargs array, apply + * reference casts as necessary, and unbox and widen primitive arguments. * The return value of the invoker will be an {@code Object} reference, * boxing a primitive value if the original type returns a primitive, * and always null if the original type returns void. *

    * This method is equivalent to the following code (though it may be more efficient): *

    -     * MethodHandle invoker = exactInvoker(type);
    -     * MethodType vaType = MethodType.makeGeneric(objectArgCount, true);
    +     * MethodHandle invoker = lookup().findVirtual(MethodHandle.class, "invokeGeneric", type);
    +     * MethodType vaType = MethodType.genericMethodType(objectArgCount, true);
          * vaType = vaType.insertParameterType(0, MethodHandle.class);
    -     * return spreadArguments(invoker, vaType);
    +     * int spreadArgCount = type.parameterCount - objectArgCount;
    +     * invoker = invoker.asSpreader(Object.class, spreadArgCount);
    +     * return invoker.asType(vaType);
          * 
    * @param type the desired target type * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments @@ -881,7 +906,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle which will take a invoke any method handle of the * given type. The resulting invoker will have a type which is * exactly equal to the desired type, except that it will accept @@ -889,7 +913,7 @@ public class MethodHandles { *

    * This method is equivalent to the following code (though it may be more efficient): *

    -     * lookup().findVirtual(MethodHandle.class, "invoke", type);
    +     * lookup().findVirtual(MethodHandle.class, "invokeExact", type);
          * 
    * @param type the desired target type * @return a method handle suitable for invoking any method handle of the given type @@ -900,37 +924,16 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: + * METHOD WILL BE REMOVED FOR PFD: * Produce a method handle equivalent to an invokedynamic instruction * which has been linked to the given call site. - * Along with {@link Lookup#findVirtual}, {@link Lookup#findStatic}, - * and {@link Lookup#findSpecial}, this completes the emulation - * of the JVM's {@code invoke} instructions. - *

    This method is equivalent to the following code: - *

    -     * MethodHandle getTarget, invoker, result;
    -     * getTarget = lookup().bind(site, "getTarget", methodType(MethodHandle.class));
    -     * invoker = exactInvoker(site.type());
    -     * result = foldArguments(invoker, getTarget)
    -     * 
    * @return a method handle which always invokes the call site's target + * @deprecated Use {@link CallSite#dynamicInvoker} instead. */ public static MethodHandle dynamicInvoker(CallSite site) throws NoAccessException { - MethodHandle getCSTarget = GET_TARGET; - if (getCSTarget == null) { - try { - GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP. - findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); - } catch (NoAccessException ex) { - throw new InternalError(); - } - } - MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site); - MethodHandle invoker = exactInvoker(site.type()); - return foldArguments(invoker, getTarget); + return site.dynamicInvoker(); } - private static MethodHandle GET_TARGET = null; // link this lazily, not eagerly static Invokers invokers(MethodType type) { return MethodTypeImpl.invokers(IMPL_TOKEN, type); @@ -974,23 +977,23 @@ public class MethodHandles { if (t0.isPrimitive()) return Wrapper.asPrimitiveType(t1).cast(value); else - return Wrapper.OBJECT.cast(value, t1); + return Wrapper.OBJECT.convert(value, t1); } boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive(); if (!prim0) { // check contract with caller - Wrapper.OBJECT.cast(value, t0); + Wrapper.OBJECT.convert(value, t0); if (!prim1) { - return Wrapper.OBJECT.cast(value, t1); + return Wrapper.OBJECT.convert(value, t1); } // convert reference to primitive by unboxing Wrapper w1 = Wrapper.forPrimitiveType(t1); - return w1.cast(value, t1); + return w1.convert(value, t1); } // check contract with caller: Wrapper.asWrapperType(t0).cast(value); Wrapper w1 = Wrapper.forPrimitiveType(t1); - return w1.cast(value, t1); + return w1.convert(value, t1); } static @@ -1011,7 +1014,7 @@ public class MethodHandles { * Produce a method handle which adapts the type of the * given method handle to a new type by pairwise argument conversion. * The original type and new type must have the same number of arguments. - * The resulting method handle is guaranteed to confess a type + * The resulting method handle is guaranteed to report a type * which is equal to the desired new type. *

    * If the original type and new type are equal, returns target. @@ -1023,34 +1026,21 @@ public class MethodHandles { * Given those types T0, T1, one of the following conversions is applied * if possible: *

      - *
    • If T0 and T1 are references, and T1 is not an interface type, - * then a cast to T1 is applied. + *
    • If T0 and T1 are references, then a cast to T1 is applied. * (The types do not need to be related in any particular way.) - *
    • If T0 and T1 are references, and T1 is an interface type, - * then the value of type T0 is passed as a T1 without a cast. - * (This treatment of interfaces follows the usage of the bytecode verifier.) - *
    • If T0 and T1 are primitives, then a Java casting - * conversion (JLS 5.5) is applied, if one exists. - *
    • If T0 and T1 are primitives and one is boolean, - * the boolean is treated as a one-bit unsigned integer. - * (This treatment follows the usage of the bytecode verifier.) - * A conversion from another primitive type behaves as if - * it first converts to byte, and then masks all but the low bit. + *
    • If T0 and T1 are primitives, then a Java method invocation + * conversion (JLS 5.3) is applied, if one exists. *
    • If T0 is a primitive and T1 a reference, a boxing * conversion is applied if one exists, possibly followed by - * an reference conversion to a superclass. + * a reference conversion to a superclass. * T1 must be a wrapper class or a supertype of one. - * If T1 is a wrapper class, T0 is converted if necessary - * to T1's primitive type by one of the preceding conversions. - * Otherwise, T0 is boxed, and its wrapper converted to T1. *
    • If T0 is a reference and T1 a primitive, an unboxing - * conversion is applied if one exists, possibly preceded by - * a reference conversion to a wrapper class. + * conversion will be applied at runtime, possibly followed + * by a Java method invocation conversion (JLS 5.3) + * on the primitive value. (These are the widening conversions.) * T0 must be a wrapper class or a supertype of one. - * If T0 is a wrapper class, its primitive value is converted - * if necessary to T1 by one of the preceding conversions. - * Otherwise, T0 is converted directly to the wrapper type for T1, - * which is then unboxed. + * (In the case where T0 is Object, these are the conversions + * allowed by java.lang.reflect.Method.invoke.) *
    • If the return type T1 is void, any returned value is discarded *
    • If the return type T0 is void and T1 a reference, a null value is introduced. *
    • If the return type T0 is void and T1 a primitive, a zero value is introduced. @@ -1060,8 +1050,9 @@ public class MethodHandles { * @return a method handle which delegates to {@code target} after performing * any necessary argument conversions, and arranges for any * necessary return value conversions - * @throws IllegalArgumentException if the conversion cannot be made + * @throws WrongMethodTypeException if the conversion cannot be made * @see MethodHandle#asType + * @see MethodHandles#explicitCastArguments */ public static MethodHandle convertArguments(MethodHandle target, MethodType newType) { @@ -1081,9 +1072,88 @@ public class MethodHandles { /** * PROVISIONAL API, WORK IN PROGRESS: + * Produce a method handle which adapts the type of the + * given method handle to a new type by pairwise argument conversion. + * The original type and new type must have the same number of arguments. + * The resulting method handle is guaranteed to report a type + * which is equal to the desired new type. + *

      + * If the original type and new type are equal, returns target. + *

      + * The same conversions are allowed as for {@link #convertArguments convertArguments}, + * and some additional conversions are also applied if those conversions fail. + * Given types T0, T1, one of the following conversions is applied + * in addition, if the conversions specified for {@code convertArguments} + * would be insufficient: + *

        + *
      • If T0 and T1 are references, and T1 is an interface type, + * then the value of type T0 is passed as a T1 without a cast. + * (This treatment of interfaces follows the usage of the bytecode verifier.) + *
      • If T0 and T1 are primitives and one is boolean, + * the boolean is treated as a one-bit unsigned integer. + * (This treatment follows the usage of the bytecode verifier.) + * A conversion from another primitive type behaves as if + * it first converts to byte, and then masks all but the low bit. + *
      • If a primitive value would be converted by {@code convertArguments} + * using Java method invocation conversion (JLS 5.3), + * Java casting conversion (JLS 5.5) may be used also. + * This allows primitives to be narrowed as well as widened. + *
      + * @param target the method handle to invoke after arguments are retyped + * @param newType the expected type of the new method handle + * @return a method handle which delegates to {@code target} after performing + * any necessary argument conversions, and arranges for any + * necessary return value conversions + * @throws WrongMethodTypeException if the conversion cannot be made + * @see MethodHandle#asType + * @see MethodHandles#convertArguments + */ + public static + MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) { + return convertArguments(target, newType); // FIXME! + } + + /* + FIXME: Reconcile javadoc with 10/22/2010 EG notes on conversion: + + Both converters arrange for their method handles to convert arguments + and return values. The conversion rules are the same for arguments + and return values, and depend only on source and target types, S and + T. The conversions allowed by castConvertArguments are a strict + superset of those performed by convertArguments. + + In all cases, if S and T are references, a simple checkcast is done. + If neither S nor T is a primitive, no attempt is made to unbox and + box. A failed conversion throws ClassCastException. + + If T is void, the value is dropped. + + For compatibility with reflection, if S is void and T is a reference, + a null value is produced. + + For compatibility with reflection, if S is a reference and T is a + primitive, S is first unboxed and then undergoes primitive conversion. + In the case of 'convertArguments', only assignment conversion is + performed (no narrowing primitive conversion). + + If S is a primitive, S is boxed, and then the above rules are applied. + If S and T are both primitives, the boxing will be undetectable; only + the primitive conversions will be apparent to the user. The key point + is that if S is a primitive type, the implementation may box it and + treat is as Object, without loss of information, or it may use a "fast + path" which does not use boxing. + + Notwithstanding the rules above, for compatibility with the verifier, + if T is an interface, it is treated as if it were Object. [KEEP THIS?] + + Also, for compatibility with the verifier, a boolean may be undergo + widening or narrowing conversion to any other primitive type. [KEEP THIS?] + */ + + /** * Produce a method handle which adapts the calling sequence of the * given method handle to a new type, by reordering the arguments. - * The resulting method handle is guaranteed to confess a type + * The resulting method handle is guaranteed to report a type * which is equal to the desired new type. *

      * The given array controls the reordering. @@ -1096,22 +1166,42 @@ public class MethodHandles { * outgoing argument will be taken from the {@code I}-th incoming * argument, where {@code I} is {@code reorder[N]}. *

      + * No argument or return value conversions are applied. + * The type of each incoming argument, as determined by {@code newType}, + * must be identical to the type of the corresponding outgoing argument + * or arguments in the target method handle. + * The return type of {@code newType} must be identical to the return + * type of the original target. + *

      * The reordering array need not specify an actual permutation. * An incoming argument will be duplicated if its index appears * more than once in the array, and an incoming argument will be dropped * if its index does not appear in the array. - *

      - * Pairwise conversions are applied as needed to arguments and return - * values, as with {@link #convertArguments}. + * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments}, + * incoming arguments which are not mentioned in the reordering array + * are may be any type, as determined only by {@code newType}. + *

      +MethodType intfn1 = MethodType.methodType(int.class, int.class);
      +MethodType intfn2 = MethodType.methodType(int.class, int.class, int.class);
      +MethodHandle sub = ... {int x, int y => x-y} ...;
      +assert(sub.type().equals(intfn2));
      +MethodHandle sub1 = MethodHandles.permuteArguments(sub, intfn2, 0, 1);
      +MethodHandle rsub = MethodHandles.permuteArguments(sub, intfn2, 1, 0);
      +assert((int)rsub.invokeExact(1, 100) == 99);
      +MethodHandle add = ... {int x, int y => x+y} ...;
      +assert(add.type().equals(intfn2));
      +MethodHandle twice = MethodHandles.permuteArguments(add, intfn1, 0, 0);
      +assert(twice.type().equals(intfn1));
      +assert((int)twice.invokeExact(21) == 42);
      +     * 
      * @param target the method handle to invoke after arguments are reordered * @param newType the expected type of the new method handle * @param reorder a string which controls the reordering - * @return a method handle which delegates to {@code target} after performing - * any necessary argument motion and conversions, and arranges for any - * necessary return value conversions + * @return a method handle which delegates to {@code target} after it + * drops unused arguments and moves and/or duplicates the other arguments */ public static - MethodHandle permuteArguments(MethodHandle target, MethodType newType, int[] reorder) { + MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) { MethodType oldType = target.type(); checkReorder(reorder, newType, oldType); return MethodHandleImpl.convertArguments(IMPL_TOKEN, target, @@ -1134,33 +1224,21 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: - * Produce a method handle which adapts the type of the - * given method handle to a new type, by spreading the final argument. - * The resulting method handle is guaranteed to confess a type - * which is equal to the desired new type. - *

      - * The final parameter type of the new type must be an array type T[]. - * This is the type of what is called the spread argument. - * All other arguments of the new type are called ordinary arguments. - *

      - * The ordinary arguments of the new type are pairwise converted - * to the initial parameter types of the old type, according to the - * rules in {@link #convertArguments}. - * Any additional arguments in the old type - * are converted from the array element type T, - * again according to the rules in {@link #convertArguments}. - * The return value is converted according likewise. - *

      - * The call verifies that the spread argument is in fact an array - * of exactly the type length, i.e., the excess number of - * arguments in the old type over the ordinary arguments in the new type. - * If there are no excess arguments, the spread argument is also - * allowed to be null. - * @param target the method handle to invoke after the argument is prepended + * METHOD WILL BE REMOVED FOR PFD: + * Equivalent to the following code: + *

      +     * int spreadPos = newType.parameterCount() - 1;
      +     * Class spreadType = newType.parameterType(spreadPos);
      +     * int spreadCount = target.type().parameterCount() - spreadPos;
      +     * MethodHandle adapter = target.asSpreader(spreadType, spreadCount);
      +     * adapter = adapter.asType(newType);
      +     * return adapter;
      +     * 
      + * @param target the method handle to invoke after argument spreading * @param newType the expected type of the new method handle - * @return a new method handle which spreads its final argument, + * @return a method handle which spreads its final argument, * before calling the original method handle + * @deprecated Use {@link MethodHandle#asSpreader} */ public static MethodHandle spreadArguments(MethodHandle target, MethodType newType) { @@ -1180,21 +1258,22 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: - * Produce a method handle which adapts the type of the - * given method handle to a new type, by collecting a series of - * trailing arguments as elements to a single argument array. - *

      - * This method may be used as an inverse to {@link #spreadArguments}. - * The final parameter type of the old type must be an array type T[], - * which is the type of what is called the spread argument. - * The trailing arguments of the new type which correspond to - * the spread argument are all converted to type T and collected - * into an array before the original method is called. - * @param target the method handle to invoke after the argument is prepended + * METHOD WILL BE REMOVED FOR PFD: + * Equivalent to the following code: + *

      +     * int collectPos = target.type().parameterCount() - 1;
      +     * Class collectType = target.type().parameterType(collectPos);
      +     * if (!collectType.isArray())  collectType = Object[].class;
      +     * int collectCount = newType.parameterCount() - collectPos;
      +     * MethodHandle adapter = target.asCollector(collectType, collectCount);
      +     * adapter = adapter.asType(newType);
      +     * return adapter;
      +     * 
      + * @param target the method handle to invoke after argument collection * @param newType the expected type of the new method handle - * @return a new method handle which collects some trailing argument + * @return a method handle which collects some trailing argument * into an array, before calling the original method handle + * @deprecated Use {@link MethodHandle#asCollector} instead. */ public static MethodHandle collectArguments(MethodHandle target, MethodType newType) { @@ -1214,6 +1293,92 @@ public class MethodHandles { /** * PROVISIONAL API, WORK IN PROGRESS: + * Produce a method handle of the requested return type which returns the given + * constant value every time it is invoked. + *

      + * Before the method handle is returned, the passed-in value is converted to the requested type. + * If the requested type is primitive, widening primitive conversions are attempted, + * else reference conversions are attempted. + *

      The returned method handle is equivalent to {@code identity(type).bindTo(value)}, + * unless the type is {@code void}, in which case it is {@code identity(type)}. + * @param type the return type of the desired method handle + * @param value the value to return + * @return a method handle of the given return type and no arguments, which always returns the given value + * @throws WrongMethodTypeException if the value cannot be converted to the required return type + */ + public static + MethodHandle constant(Class type, Object value) { + if (type.isPrimitive()) { + if (type == void.class) return identity(type); + Wrapper w = Wrapper.forPrimitiveType(type); + return identity(type).bindTo(w.convert(value, type)); + } else { + return identity(type).bindTo(type.cast(value)); + } + } + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Produce a method handle of the requested type which returns the given + * constant value every time it is invoked. + *

      + * Before the method handle is returned, the passed-in value is converted to the requested return type, + * as if by {@link #explicitCastArguments #explicitCastArguments}. + * That is, if the return type is primitive, the value is unboxed, + * and the primitive value is widened and/or narrowed. + * Otherwise, reference conversions are attempted. + * @param type the type of the desired method handle + * @param value the value to return + * @return a method handle of the given return type and no arguments, which always returns the given value + * @throws WrongMethodTypeException if the value cannot be converted to the required return type + */ + public static + MethodHandle constant(MethodType type, Object value) { + MethodHandle target = constant(type.returnType(), value); + int len = type.parameterCount(); + if (len == 0) + return target.asType(type); + target = target.asType(type.dropParameterTypes(0, len)); + return dropArguments(target, 0, type.parameterList().subList(0, len)); + } + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Produce a method handle which returns its sole argument when invoked. + *

      The identity function for {@code void} takes no arguments and returns no values. + * @param type the type of the sole parameter and return value of the desired method handle + * @return a unary method handle which accepts and returns the given type + */ + public static + MethodHandle identity(Class type) { + return ValueConversions.identity(type); + } + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Produce a method handle of the requested type which returns its argument when invoked. + * If the return type differs from the first argument type, the argument will be + * converted as if by {@link #explicitCastArguments explicitCastArguments}. + * All other arguments are discarded. + *

      The identity function for {@code void} discards all its arguments. + *

      + * @param type the type of the desired method handle + * @return a method handle of the given type, which always returns its first argument + * @throws WrongMethodTypeException if the first argument cannot be converted to the required return type + */ + public static + MethodHandle identity(MethodType type) { + MethodHandle target = identity(type.returnType()); + int len = type.parameterCount(); + if (len == 1) + return explicitCastArguments(target, type); + if (len == 0) + throw new IllegalArgumentException("not enough arguments"); + target = explicitCastArguments(target, type.dropParameterTypes(1, len)); + return dropArguments(target, 1, type.parameterList().subList(1, len)); + } + + /** * Produce a method handle which calls the original method handle {@code target}, * after inserting the given argument(s) at the given position. * The formal parameters to {@code target} which will be supplied by those @@ -1233,8 +1398,9 @@ public class MethodHandles { * @param target the method handle to invoke after the argument is inserted * @param pos where to insert the argument (zero for the first) * @param values the series of arguments to insert - * @return a new method handle which inserts an additional argument, + * @return a method handle which inserts an additional argument, * before calling the original method handle + * @see MethodHandle#bindTo */ public static MethodHandle insertArguments(MethodHandle target, int pos, Object... values) { @@ -1267,14 +1433,7 @@ public class MethodHandles { return result; } - @Deprecated // "use MethodHandles.insertArguments instead" - public static - MethodHandle insertArgument(MethodHandle target, int pos, Object value) { - return insertArguments(target, pos, value); - } - /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle which calls the original method handle, * after dropping the given argument(s) at the given position. * The type of the new method handle will insert the given argument @@ -1302,10 +1461,10 @@ public class MethodHandles { * MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class); * System.out.println((String) d12.invokeExact("x", 12, true, "z")); // xz *

  7. - * @param target the method handle to invoke after the argument is dropped - * @param valueTypes the type(s) of the argument to drop - * @param pos which argument to drop (zero for the first) - * @return a new method handle which drops an argument of the given type, + * @param target the method handle to invoke after the arguments are dropped + * @param valueTypes the type(s) of the argument(s) to drop + * @param pos position of first argument to drop (zero for the leftmost) + * @return a method handle which drops arguments of the given types, * before calling the original method handle */ public static @@ -1323,23 +1482,36 @@ public class MethodHandles { return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos); } + /** + * Produce a method handle which calls the original method handle, + * after dropping the given argument(s) at the given position. + * The type of the new method handle will insert the given argument + * type(s), at that position, into the original handle's type. + * This method is equivalent to the following code: + * + * {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes)) + * + * @param target the method handle to invoke after the arguments are dropped + * @param valueTypes the type(s) of the argument(s) to drop + * @param pos position of first argument to drop (zero for the leftmost) + * @return a method handle which drops arguments of the given types, + * before calling the original method handle + */ public static MethodHandle dropArguments(MethodHandle target, int pos, Class... valueTypes) { return dropArguments(target, pos, Arrays.asList(valueTypes)); } /** - * PROVISIONAL API, WORK IN PROGRESS: * Adapt a target method handle {@code target} by pre-processing * one or more of its arguments, each with its own unary filter function, * and then calling the target with each pre-processed argument * replaced by the result of its corresponding filter function. *

    * The pre-processing is performed by one or more method handles, - * specified in the non-null elements of the {@code filters} array. - * (If there are no such elements, the original target is returned.) - * Each filter (that is, each non-null element of {@code filters}) - * is applied to the corresponding argument of the adapter. + * specified in the elements of the {@code filters} array. + * (If there are no elements in the array, the original target is returned.) + * Each filter is applied to the corresponding argument of the adapter. *

    * If a filter {@code F} applies to the {@code N}th argument of * the method handle, then {@code F} must be a method handle which @@ -1349,46 +1521,49 @@ public class MethodHandles { * The return type of {@code F} must be identical to the corresponding * parameter type of the target. *

    - * It is an error if there are non-null elements of {@code filters} + * It is an error if there are elements of {@code filters} * which do not correspond to argument positions in the target. - * The actual length of the target array may be any number, it need - * not be the same as the parameter count of the target type. - * (This provides an easy way to filter just the first argument or two - * of a target method handle.) - *

    Here is pseudocode for the resulting adapter: - *

    -     * // there are N arguments in the A sequence
    -     * T target(A[N]...);
    -     * [i<N] V[i] filter[i](B[i]) = filters[i] ?: identity;
    -     * T adapter(B[N]... b) {
    -     *   A[N] a...;
    -     *   [i<N] a[i] = filter[i](b[i]);
    -     *   return target(a...);
    -     * }
    +     * Example:
    +     * 

    +import static java.dyn.MethodHandles.*;
    +import static java.dyn.MethodType.*;
    +...
    +MethodHandle cat = lookup().findVirtual(String.class,
    +  "concat", methodType(String.class, String.class));
    +MethodHandle upcase = lookup().findVirtual(String.class,
    +  "toUpperCase", methodType(String.class));
    +System.out.println((String) cat.invokeExact("x", "y")); // xy
    +MethodHandle f0 = filterArguments(cat, 0, upcase);
    +System.out.println((String) f0.invokeExact("x", "y")); // Xy
    +MethodHandle f1 = filterArguments(cat, 1, upcase);
    +System.out.println((String) f1.invokeExact("x", "y")); // xY
    +MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
    +System.out.println((String) f2.invokeExact("x", "y")); // XY
          * 
    * @param target the method handle to invoke after arguments are filtered + * @param pos the position of the first argument to filter * @param filters method handles to call initially on filtered arguments * @return method handle which incorporates the specified argument filtering logic - * @throws IllegalArgumentException if a non-null element of {@code filters} - * does not match a corresponding argument type of {@code target} + * @throws IllegalArgumentException if an element of {@code filters} is null or + * does not match a corresponding argument type of {@code target} as described above */ public static - MethodHandle filterArguments(MethodHandle target, MethodHandle... filters) { + MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) { MethodType targetType = target.type(); MethodHandle adapter = target; MethodType adapterType = targetType; - int pos = -1, maxPos = targetType.parameterCount(); + int maxPos = targetType.parameterCount(); + int curPos = pos; for (MethodHandle filter : filters) { - pos += 1; - if (filter == null) continue; - if (pos >= maxPos) + if (curPos >= maxPos) throw newIllegalArgumentException("too many filters"); MethodType filterType = filter.type(); if (filterType.parameterCount() != 1 - || filterType.returnType() != targetType.parameterType(pos)) + || filterType.returnType() != targetType.parameterType(curPos)) throw newIllegalArgumentException("target and filter types do not match"); - adapterType = adapterType.changeParameterType(pos, filterType.parameterType(0)); - adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, pos, filter); + adapterType = adapterType.changeParameterType(curPos, filterType.parameterType(0)); + adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, curPos, filter); + curPos += 1; } MethodType midType = adapter.type(); if (midType != adapterType) @@ -1396,9 +1571,37 @@ public class MethodHandles { return adapter; } - /** Apply the given filter function to the return value of the given target. + /** PROVISIONAL API, WORK IN PROGRESS: + * Adapt a target method handle {@code target} by post-processing + * its return value with a unary filter function. + *

    + * If a filter {@code F} applies to the return value of + * the target method handle, then {@code F} must be a method handle which + * takes exactly one argument. The return type of {@code F} + * replaces the return type of the target + * in the resulting adapted method handle. + * The argument type of {@code F} must be identical to the + * return type of the target. + * Example: + *

    +import static java.dyn.MethodHandles.*;
    +import static java.dyn.MethodType.*;
    +...
    +MethodHandle cat = lookup().findVirtual(String.class,
    +  "concat", methodType(String.class, String.class));
    +MethodHandle length = lookup().findVirtual(String.class,
    +  "length", methodType(int.class));
    +System.out.println((String) cat.invokeExact("x", "y")); // xy
    +MethodHandle f0 = filterReturnValue(cat, length);
    +System.out.println((int) f0.invokeExact("x", "y")); // 2
    +     * 
    + * @param target the method handle to invoke before filtering the return value + * @param filter method handle to call on the return value + * @return method handle which incorporates the specified return value filtering logic + * @throws IllegalArgumentException if {@code filter} is null or + * does not match the return type of {@code target} as described above */ - /*public*/ static + public static MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) { MethodType targetType = target.type(); MethodType filterType = filter.type(); @@ -1411,7 +1614,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Adapt a target method handle {@code target} by pre-processing * some of its arguments, and then calling the target with * the result of the pre-processing, plus all original arguments. @@ -1428,10 +1630,10 @@ public class MethodHandles { * The resulting adapter is the same type as the target, except that the * initial argument type of the target is dropped. *

    - * (Note that {@link #dropArguments} can be used to remove any arguments + * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments * that either the {@code combiner} or {@code target} does not wish to receive. * If some of the incoming arguments are destined only for the combiner, - * consider using {@link #collectArguments} instead, since those + * consider using {@link MethodHandle#asCollector} instead, since those * arguments will not need to be live on the stack on entry to the * target.) *

    @@ -1471,31 +1673,7 @@ public class MethodHandles { return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, newType, combiner); } - // /** - // * PROVISIONAL API, WORK IN PROGRESS: - // * Adapt a target method handle {@code target} by pre-processing - // * some of its arguments to derive a new target method handle. - // * Call the new target on the original arguments. - // * @param combined method handle to call initially on the incoming arguments - // * @return method handle which incorporates the specified dispatching logic - // * @throws IllegalArgumentException if the first argument type of - // * {@code combiner}'s return type is not {@link MethodHandle}, - // * or if the next argument types of {@code target} - // * are not identical with the argument types of {@code combiner} - // */ - // public static - // MethodHandle dispatchArguments(MethodType targetType, MethodHandle dispatcher) { - // MethodType dispatcherType = dispatcher.type(); - // int foldArgs = dispatcherType.parameterCount(); - // boolean ok = (targetType.parameterCount() >= foldArgs); - // if (!ok) - // throw misMatchedTypes("target and dispatcher types", targetType, dispatcherType); - // MethodHandle target = exactInvoker(targetType); - // return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, targetType, dispatcher); - // } - /** - * PROVISIONAL API, WORK IN PROGRESS: * Make a method handle which adapts a target method handle, * by guarding it with a test, a boolean-valued method handle. * If the guard fails, a fallback handle is called instead. @@ -1572,7 +1750,6 @@ public class MethodHandles { } /** - * PROVISIONAL API, WORK IN PROGRESS: * Make a method handle which adapts a target method handle, * by running it inside an exception handler. * If the target returns normally, the adapter returns that value. @@ -1635,6 +1812,7 @@ public class MethodHandles { } /** + * PROVISIONAL API, WORK IN PROGRESS: * Produce a wrapper instance of the given "SAM" type which redirects its calls to the given method handle. * A SAM type is a type which declares a single abstract method. * Additionally, it must have either no constructor (as an interface) @@ -1663,7 +1841,6 @@ public class MethodHandles { *

  8. the SAM type itself and any methods in the SAM type *
  9. the supertypes of the SAM type (if any) and their methods *
  10. {@link Object} and its methods - *
  11. {@link MethodHandleProvider} and its methods * *

    * No stable mapping is promised between the SAM type and @@ -1684,9 +1861,9 @@ public class MethodHandles { */ // ISSUE: Should we delegate equals/hashCode to the targets? // Not useful unless there is a stable equals/hashCode behavior - // for MethodHandle, and for MethodHandleProvider.asMethodHandle. + // for MethodHandle, but there isn't. public static - T asInstance(MethodHandle target, Class samType) { + T asInstance(final MethodHandle target, final Class samType) { // POC implementation only; violates the above contract several ways final Method sam = getSamMethod(samType); if (sam == null) @@ -1694,21 +1871,42 @@ public class MethodHandles { MethodType samMT = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes()); if (!samMT.equals(target.type())) throw new IllegalArgumentException("wrong method type"); - final MethodHandle mh = target; return samType.cast(Proxy.newProxyInstance( samType.getClassLoader(), - new Class[]{ samType, MethodHandleProvider.class }, + new Class[]{ samType, AsInstanceObject.class }, new InvocationHandler() { + private Object getArg(String name) { + if ((Object)name == "getAsInstanceTarget") return target; + if ((Object)name == "getAsInstanceType") return samType; + throw new AssertionError(); + } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (method.getDeclaringClass() == MethodHandleProvider.class) { - return method.invoke(mh, args); - } + if (method.getDeclaringClass() == AsInstanceObject.class) + return getArg(method.getName()); assert method.equals(sam) : method; - return mh.invokeVarargs(args); + return target.invokeVarargs(args); } })); } + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Interface implemented by every object which is produced by {@link #asInstance asInstance}. + * The methods of this interface allow a caller to recover the parameters + * to {@code asInstance}. + * This allows applications to repeatedly convert between method handles + * and SAM objects, without the risk of creating unbounded delegation chains. + */ + public interface AsInstanceObject { + /** Produce or recover a target method handle which is behaviorally + * equivalent to the SAM method of this object. + */ + public MethodHandle getAsInstanceTarget(); + /** Recover the SAM type for which this object was created. + */ + public Class getAsInstanceType(); + } + private static Method getSamMethod(Class samType) { Method sam = null; diff --git a/jdk/src/share/classes/java/dyn/MethodType.java b/jdk/src/share/classes/java/dyn/MethodType.java index e7e948bdb7e..1e8fce7adf2 100644 --- a/jdk/src/share/classes/java/dyn/MethodType.java +++ b/jdk/src/share/classes/java/dyn/MethodType.java @@ -119,7 +119,7 @@ class MethodType implements java.lang.reflect.Type { for (Class ptype : ptypes) { ptype.equals(ptype); // null check if (ptype == void.class) - throw newIllegalArgumentException("void parameter: "+this); + throw newIllegalArgumentException("parameter type cannot be void"); } } @@ -139,10 +139,6 @@ class MethodType implements java.lang.reflect.Type { MethodType methodType(Class rtype, Class[] ptypes) { return makeImpl(rtype, ptypes, false); } - @Deprecated public static - MethodType make(Class rtype, Class[] ptypes) { - return methodType(rtype, ptypes); - } /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. */ public static @@ -150,10 +146,6 @@ class MethodType implements java.lang.reflect.Type { boolean notrust = false; // random List impl. could return evil ptypes array return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust); } - @Deprecated public static - MethodType make(Class rtype, List> ptypes) { - return methodType(rtype, ptypes); - } /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * The leading parameter type is prepended to the remaining array. @@ -165,10 +157,6 @@ class MethodType implements java.lang.reflect.Type { System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length); return makeImpl(rtype, ptypes1, true); } - @Deprecated public static - MethodType make(Class rtype, Class ptype0, Class... ptypes) { - return methodType(rtype, ptype0, ptypes); - } /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * The resulting method has no parameter types. @@ -177,10 +165,6 @@ class MethodType implements java.lang.reflect.Type { MethodType methodType(Class rtype) { return makeImpl(rtype, NO_PTYPES, true); } - @Deprecated public static - MethodType make(Class rtype) { - return methodType(rtype); - } /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * The resulting method has the single given parameter type. @@ -189,10 +173,6 @@ class MethodType implements java.lang.reflect.Type { MethodType methodType(Class rtype, Class ptype0) { return makeImpl(rtype, new Class[]{ ptype0 }, true); } - @Deprecated public static - MethodType make(Class rtype, Class ptype0) { - return methodType(rtype, ptype0); - } /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * The resulting method has the same parameter types as {@code ptypes}, @@ -202,10 +182,6 @@ class MethodType implements java.lang.reflect.Type { MethodType methodType(Class rtype, MethodType ptypes) { return makeImpl(rtype, ptypes.ptypes, true); } - @Deprecated public static - MethodType make(Class rtype, MethodType ptypes) { - return methodType(rtype, ptypes); - } /** * Sole factory method to find or create an interned method type. @@ -275,10 +251,6 @@ class MethodType implements java.lang.reflect.Type { } return mt; } - @Deprecated public static - MethodType makeGeneric(int objectArgCount, boolean varargs) { - return genericMethodType(objectArgCount, varargs); - } /** * All parameters and the return type will be Object. @@ -290,10 +262,6 @@ class MethodType implements java.lang.reflect.Type { MethodType genericMethodType(int objectArgCount) { return genericMethodType(objectArgCount, false); } - @Deprecated public static - MethodType makeGeneric(int objectArgCount) { - return genericMethodType(objectArgCount); - } /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * @param num the index (zero-based) of the parameter type to change @@ -307,18 +275,6 @@ class MethodType implements java.lang.reflect.Type { return makeImpl(rtype, nptypes, true); } - /** Convenience method for {@link #insertParameterTypes}. - * @deprecated Use {@link #insertParameterTypes} instead. - */ - @Deprecated - public MethodType insertParameterType(int num, Class nptype) { - int len = ptypes.length; - Class[] nptypes = Arrays.copyOfRange(ptypes, 0, len+1); - System.arraycopy(nptypes, num, nptypes, num+1, len-num); - nptypes[num] = nptype; - return makeImpl(rtype, nptypes, true); - } - /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * @param num the position (zero-based) of the inserted parameter type(s) * @param ptypesToInsert zero or more a new parameter types to insert into the parameter list @@ -336,6 +292,14 @@ class MethodType implements java.lang.reflect.Type { return makeImpl(rtype, nptypes, true); } + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. + * @param ptypesToInsert zero or more a new parameter types to insert after the end of the parameter list + * @return the same type, except with the selected parameter(s) appended + */ + public MethodType appendParameterTypes(Class... ptypesToInsert) { + return insertParameterTypes(parameterCount(), ptypesToInsert); + } + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * @param num the position (zero-based) of the inserted parameter type(s) * @param ptypesToInsert zero or more a new parameter types to insert into the parameter list @@ -377,14 +341,6 @@ class MethodType implements java.lang.reflect.Type { return makeImpl(rtype, nptypes, true); } - /** Convenience method for {@link #dropParameterTypes}. - * @deprecated Use {@link #dropParameterTypes} instead. - */ - @Deprecated - public MethodType dropParameterType(int num) { - return dropParameterTypes(num, num+1); - } - /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * @param nrtype a return parameter type to replace the old one with * @return the same type, except with the return type change @@ -690,14 +646,4 @@ class MethodType implements java.lang.reflect.Type { public String toMethodDescriptorString() { return BytecodeDescriptor.unparse(this); } - - /** Temporary alias for toMethodDescriptorString; delete after M3. */ - public String toBytecodeString() { - return toMethodDescriptorString(); - } - /** Temporary alias for fromMethodDescriptorString; delete after M3. */ - public static MethodType fromBytecodeString(String descriptor, ClassLoader loader) - throws IllegalArgumentException, TypeNotPresentException { - return fromMethodDescriptorString(descriptor, loader); - } } diff --git a/jdk/src/share/classes/java/dyn/VolatileCallSite.java b/jdk/src/share/classes/java/dyn/VolatileCallSite.java new file mode 100644 index 00000000000..4a28431aae9 --- /dev/null +++ b/jdk/src/share/classes/java/dyn/VolatileCallSite.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.dyn; + +import java.util.List; + +/** + * PROVISIONAL API, WORK IN PROGRESS: + * A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable. + * An {@code invokedynamic} instruction linked to a {@code VolatileCallSite} sees updates + * to its call site target immediately, even if the update occurs in another thread. + *

    + * Also, a volatile call site has the ability to be invalidated, + * or reset to a well-defined fallback state. + *

    + * A volatile call site can be used as a switch to control the behavior + * of another method handle. For example: + *

    +MethodHandle strcat = MethodHandles.lookup()
    +  .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class));
    +MethodHandle trueCon  = MethodHandles.constant(boolean.class, true);
    +MethodHandle falseCon = MethodHandles.constant(boolean.class, false);
    +VolatileCallSite switcher = new VolatileCallSite(trueCon, falseCon);
    +// following steps may be repeated to re-use the same switcher:
    +MethodHandle worker1 = strcat;
    +MethodHandle worker2 = MethodHandles.permuteArguments(strcat, strcat.type(), 1, 0);
    +MethodHandle worker = MethodHandles.guardWithTest(switcher.dynamicInvoker(), worker1, worker2);
    +System.out.println((String) worker.invokeExact("met", "hod"));  // method
    +switcher.invalidate();
    +System.out.println((String) worker.invokeExact("met", "hod"));  // hodmet
    + * 
    + * In this case, the fallback path (worker2) does not cause a state change. + * In a real application, the fallback path could cause call sites to relink + * themselves in response to a global data structure change. + * Thus, volatile call sites can be used to build dependency mechanisms. + * @author John Rose, JSR 292 EG + */ +public class VolatileCallSite extends CallSite { + volatile MethodHandle fallback; + + /** Create a call site with a volatile target. + * The initial target and fallback are both set to a method handle + * of the given type which will throw {@code IllegalStateException}. + */ + public VolatileCallSite(MethodType type) { + super(type); + fallback = target; + } + + /** Create a call site with a volatile target. + * The fallback and target are both set to the same initial value. + */ + public VolatileCallSite(MethodHandle target) { + super(target); + fallback = target; + } + + /** Create a call site with a volatile target. + * The fallback and target are set to the given initial values. + */ + public VolatileCallSite(MethodHandle target, MethodHandle fallback) { + this(target); + checkTargetChange(target, fallback); // make sure they have the same type + this.fallback = fallback; + } + + /** Internal override to nominally final getTarget. */ + @Override + MethodHandle getTarget0() { + return getTargetVolatile(); + } + + /** + * Set the target method of this call site, as a volatile variable. + * Has the same effect as {@link CallSite#setTarget}, with the additional + * effects associated with volatiles, in the Java Memory Model. + */ + @Override public void setTarget(MethodHandle newTarget) { + checkTargetChange(getTargetVolatile(), newTarget); + setTargetVolatile(newTarget); + } + + /** + * Return the fallback target for this call site. + * It is initialized to the target the call site had when it was constructed, + * but it may be changed by {@link setFallbackTarget}. + *

    + * Like the regular target of a volatile call site, + * the fallback target also has the behavior of a volatile variable. + */ + public MethodHandle getFallbackTarget() { + return fallback; + } + + /** + * Update the fallback target for this call site. + * @see #getFallbackTarget + */ + public void setFallbackTarget(MethodHandle newFallbackTarget) { + checkTargetChange(fallback, newFallbackTarget); + fallback = newFallbackTarget; + } + + /** + * Reset this call site to a known state by changing the target to the fallback target value. + * Equivalent to {@code setTarget(getFallbackTarget())}. + */ + public void invalidate() { + setTargetVolatile(getFallbackTarget()); + } + + /** + * Reset all call sites in a list by changing the target of each to its fallback value. + */ + public static void invalidateAll(List sites) { + for (VolatileCallSite site : sites) { + site.invalidate(); + } + } + +} diff --git a/jdk/src/share/classes/java/dyn/package-info.java b/jdk/src/share/classes/java/dyn/package-info.java index 37555be14b4..428ca60acd8 100644 --- a/jdk/src/share/classes/java/dyn/package-info.java +++ b/jdk/src/share/classes/java/dyn/package-info.java @@ -24,7 +24,6 @@ */ /** - * PROVISIONAL API, WORK IN PROGRESS: * This package contains dynamic language support provided directly by * the Java core class libraries and virtual machine. *

    @@ -42,13 +41,6 @@ * argument and return value conversions are applied. *

  12. * - *
  13. In source code, the class {@link java.dyn.InvokeDynamic InvokeDynamic} appears to accept - * any static method invocation, of any name and any signature. - * But instead of emitting - * an {@code invokestatic} instruction for such a call, the Java compiler emits - * an {@code invokedynamic} instruction with the given name and signature. - *
  14. - * *
  15. The JVM bytecode format supports immediate constants of * the classes {@link java.dyn.MethodHandle MethodHandle} and {@link java.dyn.MethodType MethodType}. *
  16. @@ -56,7 +48,8 @@ * *

    Corresponding JVM bytecode format changes

    * The following low-level information is presented here as a preview of - * changes being made to the Java Virtual Machine specification for JSR 292. + * changes being made to the Java Virtual Machine specification for JSR 292. + * This information will be incorporated in a future version of the JVM specification. * *

    {@code invokedynamic} instruction format

    * In bytecode, an {@code invokedynamic} instruction is formatted as five bytes. @@ -64,22 +57,21 @@ * The next two bytes are a constant pool index (in the same format as for the other {@code invoke} instructions). * The final two bytes are reserved for future use and required to be zero. * The constant pool reference of an {@code invokedynamic} instruction is to a entry - * with tag {@code CONSTANT_InvokeDynamic} (decimal 17). See below for its format. - * The entry specifies the bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant), - * the dynamic invocation name, and the argument types and return type of the call. + * with tag {@code CONSTANT_InvokeDynamic} (decimal 18). See below for its format. + * (The tag value 17 is also allowed. See below.) + * The entry specifies the following information: + *
      + *
    • a bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant)
    • + *
    • the dynamic invocation name (a UTF8 string)
    • + *
    • the argument and return types of the call (encoded as a signature in a UTF8 string)
    • + *
    • optionally, a sequence of additional static arguments to the bootstrap method (constants loadable via {@code ldc})
    • + *
    *

    * Each instance of an {@code invokedynamic} instruction is called a dynamic call site. * Multiple instances of an {@code invokedynamic} instruction can share a single * {@code CONSTANT_InvokeDynamic} entry. * In any case, distinct call sites always have distinct linkage state. *

    - * Moreover, for the purpose of distinguishing dynamic call sites, - * the JVM is allowed (but not required) to make internal copies - * of {@code invokedynamic} instructions, each one - * constituting a separate dynamic call site with its own linkage state. - * Such copying, if it occurs, cannot be observed except indirectly via - * execution of bootstrap methods and target methods. - *

    * A dynamic call site is originally in an unlinked state. In this state, there is * no target method for the call site to invoke. * A dynamic call site is linked by means of a bootstrap method, @@ -90,17 +82,35 @@ * bootstrap method was specified dynamically, in a per-class basis, during class initialization.) * *

    constant pool entries for {@code invokedynamic} instructions

    - * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 17), - * it must contain exactly four more bytes. - * The first two bytes after the tag must be an index to a {@code CONSTANT_MethodHandle} - * entry, and the second two bytes must be an index to a {@code CONSTANT_NameAndType}. + * PROVISIONAL API, WORK IN PROGRESS: + * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 18), + * it must contain at least six more bytes after the tag. + * All of these bytes are grouped in pairs, + * and each pair is interpreted as a 16-bit index (in the usual {@code u2} format). + * The first pair of bytes after the tag must be an index to a {@code CONSTANT_MethodHandle} + * entry, and the second pair of bytes must be an index to a {@code CONSTANT_NameAndType}. + * The third pair of bytes specifies a count N of remaining byte pairs. + * After the tag and required bytes, there must be exactly 2N remaining bytes + * in the constant pool entry, each pair providing the index of a constant pool entry. + *

    * The first index specifies a bootstrap method used by the associated dynamic call sites. * The second index specifies the method name, argument types, and return type of the dynamic call site. * The structure of such an entry is therefore analogous to a {@code CONSTANT_Methodref}, - * except that the {@code CONSTANT_Class} reference in a {@code CONSTANT_Methodref} entry - * is replaced by a bootstrap method reference. + * except that the bootstrap method reference replaces + * the {@code CONSTANT_Class} reference of a {@code CONSTANT_Methodref} entry. + * The remaining indexes (if there is a non-zero count) specify + * additional static arguments for the bootstrap method. + *

    + * Some older JVMs may allow an older constant pool entry tag of decimal 17. + * The format and behavior of a constant pool entry with this tag is identical to + * an entry with a tag of decimal 18, except that the constant pool entry must not + * contain extra static arguments or a static argument count. + * The fixed size of such an entry is therefore four bytes after the tag. + * The value of the missing static argument count is taken to be zero. + * (Note: The Proposed Final Draft of this specification is not likely to support + * both of these formats.) * - *

    constant pool entries for {@code MethodType}s

    + *

    constant pool entries for {@linkplain java.dyn.MethodType method types}

    * If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16), * it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8} * entry which represents a method type signature. @@ -112,8 +122,13 @@ * but not initialized. * Access checking and error reporting is performed exactly as it is for * references by {@code ldc} instructions to {@code CONSTANT_Class} constants. + *

    + * Every use of this constant pool entry must lead to the same outcome. + * If the resolution of the names in the method type constant causes an exception to occur, + * this exception must be recorded by the JVM, and re-thrown on every subsequent attempt + * to use this particular constant. * - *

    constant pool entries for {@code MethodHandle}s

    + *

    constant pool entries for {@linkplain java.dyn.MethodHandle method handles}

    * If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15), * it must contain exactly three more bytes. The first byte after the tag is a subtag * value which must be in the range 1 through 9, and the last two must be an index to a @@ -129,7 +144,7 @@ *

    * As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants, * the {@code Class} or {@code MethodType} object which reifies the field or method's - * type is created. Any classes mentioned in this reificaiton will be loaded if necessary, + * type is created. Any classes mentioned in this reification will be loaded if necessary, * but not initialized, and access checking and error reporting performed as usual. *

    * The method handle itself will have a type and behavior determined by the subtag as follows: @@ -150,14 +165,29 @@ *

    * The special names {@code } and {@code } are not allowed except for subtag 8 as shown. *

    - * The verifier applies the same access checks and restrictions for these references as for the hypothetical + * The JVM verifier and linker apply the same access checks and restrictions for these references as for the hypothetical * bytecode instructions specified in the last column of the table. In particular, method handles to * private and protected members can be created in exactly those classes for which the corresponding * normal accesses are legal. *

    - * None of these constant types force class initialization. - * Method handles for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic} + * A constant may refer to a method or constructor with the {@code varargs} + * bit (hexadecimal {@code 80}) set in its modifier bitmask. + * The method handle constant produced for such a method behaves the same + * as if the {@code varargs} bit were not set. + * The argument-collecting behavior of {@code varargs} can be emulated by + * adapting the method handle constant with + * {@link java.dyn.MethodHandle#asCollector asCollector}. + * There is no provision for doing this automatically. + *

    + * Although the {@code CONSTANT_MethodHandle} and {@code CONSTANT_MethodType} constant types + * resolve class names, they do not force class initialization. + * Method handle constants for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic} * may force class initialization on their first invocation, just like the corresponding bytecodes. + *

    + * Every use of this constant pool entry must lead to the same outcome. + * If the resolution of the names in the method handle constant causes an exception to occur, + * this exception must be recorded by the JVM, and re-thrown on every subsequent attempt + * to use this particular constant. * *

    Bootstrap Methods

    * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction), @@ -181,24 +211,36 @@ * call site execution. * Linkage does not trigger class initialization. *

    - * Next, the bootstrap method call is started, with four values being stacked: + * Next, the bootstrap method call is started, with four or five values being stacked: *

      *
    • a {@code MethodHandle}, the resolved bootstrap method itself
    • - *
    • a {@code Class}, the caller class in which dynamic call site occurs
    • + *
    • a {@code MethodHandles.Lookup}, a lookup object on the caller class in which dynamic call site occurs
    • *
    • a {@code String}, the method name mentioned in the call site
    • *
    • a {@code MethodType}, the resolved type signature of the call
    • + *
    • optionally, a single object representing one or more additional static arguments
    • *
    * The method handle is then applied to the other values as if by - * {@linkplain java.dyn.MethodHandle#invokeGeneric the invokeGeneric method}. - * The returned result must be a {@link java.dyn.CallSite CallSite}, a {@link java.dyn.MethodHandle MethodHandle}, - * or another {@link java.dyn.MethodHandleProvider MethodHandleProvider} value. - * The method {@linkplain java.dyn.MethodHandleProvider#asMethodHandle asMethodHandle} - * is then called on the returned value. The result of that second - * call is the {@code MethodHandle} which becomes the - * permanent binding for the dynamic call site. - * That method handle's type must be exactly equal to the type + * {@link java.dyn.MethodHandle#invokeGeneric invokeGeneric}. + * The returned result must be a {@link java.dyn.CallSite CallSite} (or a subclass). + * The type of the call site's target must be exactly equal to the type * derived from the dynamic call site signature and passed to * the bootstrap method. + * The call site then becomes permanently linked to the dynamic call site. + *

    + * As long as each bootstrap method can be correctly invoked + * by invokeGeneric, its detailed type is arbitrary. + * For example, the first argument could be {@code Object} + * instead of {@code MethodHandles.Lookup}, and the return type + * could also be {@code Object} instead of {@code CallSite}. + *

    + * As with any method handle constant, a {@code varargs} modifier bit + * on the bootstrap method is ignored. + *

    + * Note that the first argument of the bootstrap method cannot be + * a simple {@code Class} reference. (This is a change from earlier + * versions of this specification. If the caller class is needed, + * it is easy to {@linkplain java.dyn.MethodHandles.Lookup#lookupClass() extract it} + * from the {@code Lookup} object. *

    * After resolution, the linkage process may fail in a variety of ways. * All failures are reported by an {@link java.dyn.InvokeDynamicBootstrapError InvokeDynamicBootstrapError}, @@ -206,13 +248,14 @@ * site execution. * The following circumstances will cause this: *

      + *
    • the bootstrap method cannot be resolved
    • + *
    • the bootstrap method has the wrong arity, + * causing {@code invokeGeneric} to throw {@code WrongMethodTypeException}
    • + *
    • the bootstrap method has a wrong argument or return type
    • *
    • the bootstrap method invocation completes abnormally
    • *
    • the result from the bootstrap invocation is not a reference to - * an object of type {@link java.dyn.MethodHandleProvider MethodHandleProvider}
    • - *
    • the call to {@code asMethodHandle} completes abnormally
    • - *
    • the call to {@code asMethodHandle} fails to return a reference to - * an object of type {@link java.dyn.MethodHandle MethodHandle}
    • - *
    • the method handle produced by {@code asMethodHandle} does not have + * an object of type {@link java.dyn.CallSite CallSite}
    • + *
    • the target of the {@code CallSite} does not have a target of * the expected {@code MethodType}
    • *
    *

    timing of linkage

    @@ -220,67 +263,119 @@ * The bootstrap method call implementing the linkage occurs within * a thread that is attempting a first execution. *

    - * If there are several such threads, the JVM picks one thread - * and runs the bootstrap method while the others wait for the - * invocation to terminate normally or abnormally. - *

    - * After a bootstrap method is called and a method handle target - * successfully extracted, the JVM attempts to link the instruction - * being executed to the target method handle. - * This may fail if there has been intervening linkage - * or invalidation event for the same instruction. - * If such a failure occurs, the dynamic call site must be - * re-executed from the beginning, either re-linking it - * (if it has been invalidated) or invoking the target - * (if it the instruction has been linked by some other means). - *

    - * If the instruction is linked successfully, the target method - * handle is invoked to complete the instruction execution. - * The state of linkage continues until the method containing the - * dynamic call site is garbage collected, or the dynamic call site - * is invalidated by an explicit request, - * such as {@link java.dyn.Linkage#invalidateCallerClass Linkage.invalidateCallerClass}. + * If there are several such threads, the bootstrap method may be + * invoked in several threads concurrently. + * Therefore, bootstrap methods which access global application + * data must take the usual precautions against race conditions. + * In any case, every {@code invokedynamic} instruction is either + * unlinked or linked to a unique {@code CallSite} object. *

    * In an application which requires dynamic call sites with individually * mutable behaviors, their bootstrap methods should produce distinct * {@link java.dyn.CallSite CallSite} objects, one for each linkage request. - *

    - * If a class containing {@code invokedynamic} instructions - * is {@linkplain java.dyn.Linkage#invalidateCallerClass(Class) invalidated}, - * subsequent execution of those {@code invokedynamic} instructions - * will require linking. - * It is as if they had never been executed in the first place. - * (However, invalidation does not cause constant pool entries to be - * resolved a second time.) - *

    - * Invalidation events and bootstrap method calls for a particular - * dynamic call site are globally ordered relative to each other. - * When an invokedynamic instruction is invalidated, if there is - * simultaneously a bootstrap method invocation in process - * (in the same thread or a different thread), the result - * eventually returned must not be used to link the call site. - * Put another way, when a call site is invalidated, its - * subsequent linkage (if any) must be performed by a bootstrap method - * call initiated after the invalidation occurred. + * Alternatively, an application can link a single {@code CallSite} object + * to several {@code invokedynamic} instructions, in which case + * a change to the target method will become visible at each of + * the instructions. *

    * If several threads simultaneously execute a bootstrap method for a single dynamic - * call site, the JVM must choose one target object and installs it visibly to + * call site, the JVM must choose one {@code CallSite} object and install it visibly to * all threads. Any other bootstrap method calls are allowed to complete, but their * results are ignored, and their dynamic call site invocations proceed with the originally * chosen target object. *

    - * The JVM is free to duplicate dynamic call sites. - * This means that, even if a class contains just one {@code invokedynamic} - * instruction, its bootstrap method may be executed several times, - * once for each duplicate. Thus, bootstrap method code should not - * assume an exclusive one-to-one correspondence between particular occurrences - * of {@code invokedynamic} bytecodes in class files and linkage events. + * Note: Unlike some previous versions of this specification, + * these rules do not enable the JVM to duplicate dynamic call sites, + * or to issue “causeless” bootstrap method calls. + * Every dynamic call site transitions at most once from unlinked to linked, + * just before its first invocation. + * + *

    static arguments to the bootstrap method

    + * PROVISIONAL API, WORK IN PROGRESS: + * An {@code invokedynamic} instruction specifies at least three arguments + * to pass to its bootstrap method: + * The caller class (expressed as a {@link java.dyn.MethodHandles.Lookup Lookup object}, + * the name (extracted from the {@code CONSTANT_NameAndType} entry), + * and the type (also extracted from the {@code CONSTANT_NameAndType} entry). + * The {@code invokedynamic} instruction may specify additional metadata values + * to pass to its bootstrap method. + * Collectively, these values are called static arguments to the + * {@code invokedynamic} instruction, because they are used once at link + * time to determine the instruction's behavior on subsequent sets of + * dynamic arguments. *

    - * In principle, each individual execution of an {@code invokedynamic} - * instruction could be deemed (by a conforming implementation) to be a separate - * duplicate, requiring its own execution of the bootstrap method. - * However, implementations are expected to perform code duplication - * (if at all) in order to improve performance, not make it worse. + * Static arguments are used to communicate application-specific meta-data + * to the bootstrap method. + * Drawn from the constant pool, they may include references to classes, method handles, + * or numeric data that may be relevant to the task of linking that particular call site. + *

    + * The third byte pair in a {@code CONSTANT_InvokeDynamic} entry, if it is not zero, + * counts up to 65535 additional constant pool indexes which contribute to a static argument. + * Each of these indexes must refer to one of a type of constant entry which is compatible with + * the {@code ldc} instruction. + * Before the bootstrap method is invoked, each index is used to compute an {@code Object} + * reference to the indexed value in the constant pool. + * If the value is a primitive type, it is converted to a reference by boxing conversion. + * The valid constant pool entries are listed in this table: + * + * + * + * + * + * + * + * + * + * + * + *
    entry typeargument typeargument value
    CONSTANT_Stringjava.lang.Stringthe indexed string literal
    CONSTANT_Classjava.lang.Classthe indexed class, resolved
    CONSTANT_Integerjava.lang.Integerthe indexed int value
    CONSTANT_Longjava.lang.Longthe indexed long value
    CONSTANT_Floatjava.lang.Floatthe indexed float value
    CONSTANT_Doublejava.lang.Doublethe indexed double value
    CONSTANT_MethodHandlejava.dyn.MethodHandlethe indexed method handle constant
    CONSTANT_MethodTypejava.dyn.MethodTypethe indexed method type constant
    + *
    + *

    + * If a given {@code invokedynamic} instruction specifies no static arguments, + * the instruction's bootstrap method will be invoked on three arguments, + * conveying the instruction's caller class, name, and method type. + * If the {@code invokedynamic} instruction specifies one or more static arguments, + * a fourth argument will be passed to the bootstrap argument, + * either an {@code Object} reference to the sole extra argument (if there is one) + * or an {@code Object} array of references to all the arguments (if there are two or more), + * as if the bootstrap method is a variable-arity method. + * + * + * + * + * + * + *
    Nsample bootstrap method
    0CallSite bootstrap(Lookup caller, String name, MethodType type)
    1CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg)
    2CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)
    + *
    + *

    + * The argument and return types listed here are used by the {@code invokeGeneric} + * call to the bootstrap method. + * As noted above, the actual method type of the bootstrap method can vary. + * For example, the fourth argument could be {@code MethodHandle}, + * if that is the type of the corresponding constant in + * the {@code CONSTANT_InvokeDynamic} entry. + * In that case, the {@code invokeGeneric} call will pass the extra method handle + * constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric} + * will cast the reference back to {@code MethodHandle} before invoking the bootstrap method. + * (If a string constant were passed instead, by badly generated code, that cast would then fail.) + *

    + * If the fourth argument is an array, the array element type must be {@code Object}, + * since object arrays (as produced by the JVM at this point) cannot be converted + * to other array types. + *

    + * If an array is provided, it will appear to be freshly allocated. + * That is, the same array will not appear to two bootstrap method calls. + *

    + * Extra bootstrap method arguments are intended to allow language implementors + * to safely and compactly encode metadata. + * In principle, the name and extra arguments are redundant, + * since each call site could be given its own unique bootstrap method. + * Such a practice is likely to produce large class files and constant pools. + *

    + * The Proposed Final Draft of JSR 292 may remove extra static arguments, + * with the associated constant tag of 18, leaving the constant tag 17. + * If the constant tag of 18 is retained, the constant tag 17 may be removed + * for the sake of simplicity. * * @author John Rose, JSR 292 EG */ diff --git a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java b/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java index 65bbd372b9c..06a24faba49 100644 --- a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java +++ b/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java @@ -487,7 +487,7 @@ public class AdapterMethodHandle extends BoundMethodHandle { static class WithTypeHandler extends AdapterMethodHandle { final MethodHandle target, typeHandler; WithTypeHandler(MethodHandle target, MethodHandle typeHandler) { - super(target, target.type(), OP_RETYPE_ONLY); + super(target, target.type(), makeConv(OP_RETYPE_ONLY)); this.target = target; this.typeHandler = typeHandler.asType(TYPE_HANDLER_TYPE); } diff --git a/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java b/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java index 4f25262f46f..cfe19663a27 100644 --- a/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java +++ b/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java @@ -106,18 +106,17 @@ public class BoundMethodHandle extends MethodHandle { assert(this instanceof AdapterMethodHandle); } - /** Initialize the current object as a Java method handle, binding it + /** Initialize the current object as a self-bound method handle, binding it * as the first argument of the method handle {@code entryPoint}. * The invocation type of the resulting method handle will be the * same as {@code entryPoint}, except that the first argument * type will be dropped. */ - protected BoundMethodHandle(MethodHandle entryPoint) { - super(Access.TOKEN, entryPoint.type().dropParameterTypes(0, 1)); + protected BoundMethodHandle(Access token, MethodHandle entryPoint) { + super(token, entryPoint.type().dropParameterTypes(0, 1)); this.argument = this; // kludge; get rid of this.vmargslot = this.type().parameterSlotDepth(0); initTarget(entryPoint, 0); - assert(this instanceof JavaMethodHandle); } /** Make sure the given {@code argument} can be used as {@code argnum}-th @@ -173,6 +172,11 @@ public class BoundMethodHandle extends MethodHandle { @Override public String toString() { + return MethodHandleImpl.addTypeString(baseName(), this); + } + + /** Component of toString() before the type string. */ + protected String baseName() { MethodHandle mh = this; while (mh instanceof BoundMethodHandle) { Object info = MethodHandleNatives.getTargetInfo(mh); @@ -185,12 +189,16 @@ public class BoundMethodHandle extends MethodHandle { if (name != null) return name; else - return super.toString(); // , probably + return noParens(super.toString()); // "invoke", probably } assert(mh != this); - if (mh instanceof JavaMethodHandle) - break; // access JMH.toString(), not BMH.toString() } - return mh.toString(); + return noParens(mh.toString()); + } + + private static String noParens(String str) { + int paren = str.indexOf('('); + if (paren >= 0) str = str.substring(0, paren); + return str; } } diff --git a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java index f7c2d7099a7..f9bea6d5486 100644 --- a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java +++ b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java @@ -41,25 +41,39 @@ public class CallSiteImpl { Object info, // Caller information: MemberName callerMethod, int callerBCI) { - Class caller = callerMethod.getDeclaringClass(); + Class callerClass = callerMethod.getDeclaringClass(); + Object caller; + if (bootstrapMethod.type().parameterType(0) == Class.class) + caller = callerClass; // remove for PFD + else + caller = MethodHandleImpl.IMPL_LOOKUP.in(callerClass); if (bootstrapMethod == null) { // If there is no bootstrap method, throw IncompatibleClassChangeError. // This is a valid generic error type for resolution (JLS 12.3.3). throw new IncompatibleClassChangeError - ("Class "+caller.getName()+" has not declared a bootstrap method for invokedynamic"); + ("Class "+callerClass.getName()+" has not declared a bootstrap method for invokedynamic"); } CallSite site; try { Object binding; - if (false) // switch when invokeGeneric works - binding = bootstrapMethod.invokeGeneric(caller, name, type); - else - binding = bootstrapMethod.invokeVarargs(new Object[]{ caller, name, type }); + if (info == null) { + if (false) // switch when invokeGeneric works + binding = bootstrapMethod.invokeGeneric(caller, name, type); + else + binding = bootstrapMethod.invokeVarargs(new Object[]{ caller, name, type }); + } else { + info = maybeReBox(info); + if (false) // switch when invokeGeneric works + binding = bootstrapMethod.invokeGeneric(caller, name, type, info); + else + binding = bootstrapMethod.invokeVarargs(new Object[]{ caller, name, type, info }); + } //System.out.println("BSM for "+name+type+" => "+binding); if (binding instanceof CallSite) { site = (CallSite) binding; - } else if (binding instanceof MethodHandleProvider) { - MethodHandle target = ((MethodHandleProvider) binding).asMethodHandle(); + } else if (binding instanceof MethodHandle) { + // Transitional! + MethodHandle target = (MethodHandle) binding; site = new ConstantCallSite(target); } else { throw new ClassCastException("bootstrap method failed to produce a MethodHandle or CallSite"); @@ -79,6 +93,24 @@ public class CallSiteImpl { return site; } + private static Object maybeReBox(Object x) { + if (x instanceof Integer) { + int xi = (int) x; + if (xi == (byte) xi) + x = xi; // must rebox; see JLS 5.1.7 + return x; + } else if (x instanceof Object[]) { + Object[] xa = (Object[]) x; + for (int i = 0; i < xa.length; i++) { + if (xa[i] instanceof Integer) + xa[i] = maybeReBox(xa[i]); + } + return xa; + } else { + return x; + } + } + // This method is private in CallSite because it touches private fields in CallSite. // These private fields (vmmethod, vmindex) are specific to the JVM. private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE; diff --git a/jdk/src/share/classes/sun/dyn/FilterGeneric.java b/jdk/src/share/classes/sun/dyn/FilterGeneric.java index 1e7b594dd93..1eaf34d5a13 100644 --- a/jdk/src/share/classes/sun/dyn/FilterGeneric.java +++ b/jdk/src/share/classes/sun/dyn/FilterGeneric.java @@ -115,7 +115,7 @@ class FilterGeneric { static MethodHandle make(Kind kind, int pos, MethodHandle filter, MethodHandle target) { FilterGeneric fgen = of(kind, pos, filter.type(), target.type()); - return fgen.makeInstance(kind, pos, filter, target).asMethodHandle(); + return fgen.makeInstance(kind, pos, filter, target); } /** Return the adapter information for this target and filter type. */ @@ -225,13 +225,13 @@ class FilterGeneric { * The invoker is kept separate from the target because it can be * generated once per type erasure family, and reused across adapters. */ - static abstract class Adapter extends JavaMethodHandle { + static abstract class Adapter extends BoundMethodHandle { protected final MethodHandle filter; // transforms one or more arguments protected final MethodHandle target; // ultimate target @Override public String toString() { - return target.toString(); + return MethodHandleImpl.addTypeString(target, this); } protected boolean isPrototype() { return target == null; } @@ -246,7 +246,7 @@ class FilterGeneric { protected Adapter(MethodHandle entryPoint, MethodHandle filter, MethodHandle target) { - super(entryPoint); + super(Access.TOKEN, entryPoint); this.filter = filter; this.target = target; } diff --git a/jdk/src/share/classes/sun/dyn/FilterOneArgument.java b/jdk/src/share/classes/sun/dyn/FilterOneArgument.java index cc8ecf66d19..2712242c289 100644 --- a/jdk/src/share/classes/sun/dyn/FilterOneArgument.java +++ b/jdk/src/share/classes/sun/dyn/FilterOneArgument.java @@ -36,7 +36,7 @@ import static sun.dyn.MemberName.uncaughtException; * final method type is the responsibility of a JVM-level adapter. * @author jrose */ -public class FilterOneArgument extends JavaMethodHandle { +public class FilterOneArgument extends BoundMethodHandle { protected final MethodHandle filter; // Object -> Object protected final MethodHandle target; // Object -> Object @@ -62,7 +62,7 @@ public class FilterOneArgument extends JavaMethodHandle { } protected FilterOneArgument(MethodHandle filter, MethodHandle target) { - super(INVOKE); + super(Access.TOKEN, INVOKE); this.filter = filter; this.target = target; } diff --git a/jdk/src/share/classes/sun/dyn/FromGeneric.java b/jdk/src/share/classes/sun/dyn/FromGeneric.java index 24f40c0c1ac..3e0d215fc97 100644 --- a/jdk/src/share/classes/sun/dyn/FromGeneric.java +++ b/jdk/src/share/classes/sun/dyn/FromGeneric.java @@ -241,7 +241,7 @@ class FromGeneric { * The invoker is kept separate from the target because it can be * generated once per type erasure family, and reused across adapters. */ - static abstract class Adapter extends JavaMethodHandle { + static abstract class Adapter extends BoundMethodHandle { /* * class X<> extends Adapter { * (MH, Object**N)=>raw(R) invoker; @@ -256,7 +256,7 @@ class FromGeneric { @Override public String toString() { - return target.toString(); + return MethodHandleImpl.addTypeString(target, this); } protected boolean isPrototype() { return target == null; } @@ -271,7 +271,7 @@ class FromGeneric { protected Adapter(MethodHandle entryPoint, MethodHandle invoker, MethodHandle convert, MethodHandle target) { - super(entryPoint); + super(Access.TOKEN, entryPoint); this.invoker = invoker; this.convert = convert; this.target = target; diff --git a/jdk/src/share/classes/sun/dyn/Invokers.java b/jdk/src/share/classes/sun/dyn/Invokers.java index 2f2c92a779f..123dd53fb94 100644 --- a/jdk/src/share/classes/sun/dyn/Invokers.java +++ b/jdk/src/share/classes/sun/dyn/Invokers.java @@ -26,6 +26,7 @@ package sun.dyn; import java.dyn.*; +import sun.dyn.empty.Empty; /** * Construction and caching of often-used invokers. @@ -48,6 +49,9 @@ public class Invokers { // generic (untyped) invoker for the outgoing call; accepts a single Object[] private final /*lazy*/ MethodHandle[] varargsInvokers; + // invoker for an unbound callsite + private /*lazy*/ MethodHandle uninitializedCallSite; + /** Compute and cache information common to all collecting adapters * that implement members of the erasure-family of the given erased type. */ @@ -107,6 +111,35 @@ public class Invokers { return vaInvoker; } + private static MethodHandle THROW_UCS = null; + + public MethodHandle uninitializedCallSite() { + MethodHandle invoker = uninitializedCallSite; + if (invoker != null) return invoker; + if (targetType.parameterCount() > 0) { + MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount()); + Invokers invokers0 = MethodTypeImpl.invokers(Access.TOKEN, type0); + invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(), + 0, targetType.parameterList()); + assert(invoker.type().equals(targetType)); + uninitializedCallSite = invoker; + return invoker; + } + if (THROW_UCS == null) { + try { + THROW_UCS = MethodHandleImpl.IMPL_LOOKUP + .findStatic(CallSite.class, "uninitializedCallSite", + MethodType.methodType(Empty.class)); + } catch (NoAccessException ex) { + throw new RuntimeException(ex); + } + } + invoker = AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, targetType, THROW_UCS); + assert(invoker.type().equals(targetType)); + uninitializedCallSite = invoker; + return invoker; + } + public String toString() { return "Invokers"+targetType; } diff --git a/jdk/src/share/classes/sun/dyn/JavaMethodHandle.java b/jdk/src/share/classes/sun/dyn/JavaMethodHandle.java deleted file mode 100644 index 2ce44d1d89e..00000000000 --- a/jdk/src/share/classes/sun/dyn/JavaMethodHandle.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.dyn; - -import java.dyn.*; -import sun.dyn.Access; - -/** - * A Java method handle is a deprecated proposal for extending - * the basic method handle type with additional - * programmer defined methods and fields. - * Its behavior as a method handle is determined at instance creation time, - * by providing the new instance with an "entry point" method handle - * to handle calls. This entry point must accept a leading argument - * whose type is the Java method handle itself or a supertype, and the - * entry point is always called with the Java method handle itself as - * the first argument. This is similar to ordinary virtual methods, which also - * accept the receiver object {@code this} as an implicit leading argument. - * The {@code MethodType} of the Java method handle is the same as that - * of the entry point method handle, with the leading parameter type - * omitted. - *

    - * Here is an example of usage, creating a hybrid object/functional datum: - *

    - * class Greeter extends JavaMethodHandle {
    - *     private String greeting = "hello";
    - *     public void setGreeting(String s) { greeting = s; }
    - *     public void run() { System.out.println(greeting+", "+greetee); }
    - *     private final String greetee;
    - *     Greeter(String greetee) {
    - *         super(RUN); // alternatively, super("run")
    - *         this.greetee = greetee;
    - *     }
    - *     // the entry point function is computed once:
    - *     private static final MethodHandle RUN
    - *         = MethodHandles.lookup().findVirtual(Greeter.class, "run",
    - *               MethodType.make(void.class));
    - * }
    - * // class Main { public static void main(String... av) { ...
    - * Greeter greeter = new Greeter("world");
    - * greeter.run();  // prints "hello, world"
    - * // Statically typed method handle invocation (most direct):
    - * MethodHandle mh = greeter;
    - * mh.<void>invokeExact();  // also prints "hello, world"
    - * // Dynamically typed method handle invocation:
    - * MethodHandles.invokeExact(greeter);  // also prints "hello, world"
    - * greeter.setGreeting("howdy");
    - * mh.invokeExact();  // prints "howdy, world" (object-like mutable behavior)
    - * 
    - *

    - * In the example of {@code Greeter}, the method {@code run} provides the entry point. - * The entry point need not be a constant value; it may be independently - * computed in each call to the constructor. The entry point does not - * even need to be a method on the {@code Greeter} class, though - * that is the typical case. - *

    - * The entry point may also be provided symbolically, in which case the the - * {@code JavaMethodHandle} constructor performs the lookup of the entry point. - * This makes it possible to use {@code JavaMethodHandle} to create an anonymous - * inner class: - *

    - * // We can also do this with symbolic names and/or inner classes:
    - * MethodHandles.invokeExact(new JavaMethodHandle("yow") {
    - *     void yow() { System.out.println("yow, world"); }
    - * });
    - * 
    - *

    - * Here is similar lower-level code which works in terms of a bound method handle. - *

    - *     class Greeter {
    - *         public void run() { System.out.println("hello, "+greetee); }
    - *         private final String greetee;
    - *         Greeter(String greetee) { this.greetee = greetee; }
    - *         // the entry point function is computed once:
    - *         private static final MethodHandle RUN
    - *             = MethodHandles.findVirtual(Greeter.class, "run",
    - *                   MethodType.make(void.class));
    - *     }
    - *     // class Main { public static void main(String... av) { ...
    - *     Greeter greeter = new Greeter("world");
    - *     greeter.run();  // prints "hello, world"
    - *     MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
    - *     mh.invokeExact();  // also prints "hello, world"
    - * 
    - * Note that the method handle must be separately created as a view on the base object. - * This increases footprint, complexity, and dynamic indirections. - *

    - * Here is a pure functional value expressed most concisely as an anonymous inner class: - *

    - *     // class Main { public static void main(String... av) { ...
    - *     final String greetee = "world";
    - *     MethodHandle greeter = new JavaMethodHandle("run") {
    - *         private void run() { System.out.println("hello, "+greetee); }
    - *     }
    - *     greeter.invokeExact();  // prints "hello, world"
    - * 
    - *

    - * Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle, - * and instantiated as an anonymous class. The data structure is a handle to 1-D array, - * with a specialized index type (long). It is created by inner class, and uses - * signature-polymorphic APIs throughout. - *

    - *     abstract class AssignableMethodHandle extends JavaMethodHandle {
    - *       private final MethodHandle setter;
    - *       public MethodHandle setter() { return setter; }
    - *       public AssignableMethodHandle(String get, String set) {
    - *         super(get);
    - *         MethodType getType = this.type();
    - *         MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
    - *         this.setter = MethodHandles.publicLookup().bind(this, set, setType);
    - *       }
    - *     }
    - *     // class Main { public static void main(String... av) { ...
    - *     final Number[] stuff = { 123, 456 };
    - *     AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
    - *         public Number get(long i)           { return stuff[(int)i]; }
    - *         public void   set(long i, Object x) {        stuff[(int)i] = x; }
    - *     }
    - *     int x = (Integer) stuffPtr.<Number>invokeExact(1L);  // 456
    - *     stuffPtr.setter().<void>invokeExact(0L, (Number) 789);  // replaces 123 with 789
    - * 
    - * @see MethodHandle - * @deprecated The JSR 292 EG intends to replace {@code JavaMethodHandle} with - * an interface-based API for mixing method handle behavior with other classes. - * @author John Rose, JSR 292 EG - */ -public abstract class JavaMethodHandle - // Note: This is an implementation inheritance hack, and will be removed - // with a JVM change which moves the required hidden behavior onto this class. - extends sun.dyn.BoundMethodHandle -{ - private static final Access IMPL_TOKEN = Access.getToken(); - - /** - * When creating a {@code JavaMethodHandle}, the actual method handle - * invocation behavior will be delegated to the specified {@code entryPoint}. - * This may be any method handle which can take the newly constructed object - * as a leading parameter. - *

    - * The method handle type of {@code this} (i.e, the fully constructed object) - * will be {@code entryPoint}, minus the leading argument. - * The leading argument will be bound to {@code this} on every method - * handle invocation. - * @param entryPoint the method handle to handle calls - */ - protected JavaMethodHandle(MethodHandle entryPoint) { - super(entryPoint); - } -} diff --git a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java index 49a625367a4..85b9f01f55d 100644 --- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java +++ b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java @@ -199,7 +199,7 @@ public abstract class MethodHandleImpl { return allocator; } - static final class AllocateObject extends JavaMethodHandle { + static final class AllocateObject extends BoundMethodHandle { private static final Unsafe unsafe = Unsafe.getUnsafe(); private final Class allocateClass; @@ -207,7 +207,7 @@ public abstract class MethodHandleImpl { private AllocateObject(MethodHandle invoker, Class allocateClass, MethodHandle rawConstructor) { - super(invoker); + super(Access.TOKEN, invoker); this.allocateClass = allocateClass; this.rawConstructor = rawConstructor; } @@ -237,7 +237,7 @@ public abstract class MethodHandleImpl { } @Override public String toString() { - return allocateClass.getSimpleName(); + return addTypeString(allocateClass.getSimpleName(), this); } @SuppressWarnings("unchecked") private C allocate() throws InstantiationException { @@ -369,19 +369,19 @@ public abstract class MethodHandleImpl { return mhs[isSetter ? 1 : 0]; } - static final class FieldAccessor extends JavaMethodHandle { + static final class FieldAccessor extends BoundMethodHandle { private static final Unsafe unsafe = Unsafe.getUnsafe(); final Object base; // for static refs only final long offset; final String name; public FieldAccessor(Access token, MemberName field, boolean isSetter) { - super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic())); + super(Access.TOKEN, fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic())); this.offset = (long) field.getVMIndex(token); this.name = field.getName(); this.base = staticBase(field); } - public String toString() { return name; } + public String toString() { return addTypeString(name, this); } int getFieldI(C obj) { return unsafe.getInt(obj, offset); } void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); } @@ -910,11 +910,11 @@ public abstract class MethodHandleImpl { throw new UnsupportedOperationException("NYI"); } - private static class GuardWithTest extends JavaMethodHandle { + private static class GuardWithTest extends BoundMethodHandle { private final MethodHandle test, target, fallback; private GuardWithTest(MethodHandle invoker, MethodHandle test, MethodHandle target, MethodHandle fallback) { - super(invoker); + super(Access.TOKEN, invoker); this.test = test; this.target = target; this.fallback = fallback; @@ -948,7 +948,7 @@ public abstract class MethodHandleImpl { } @Override public String toString() { - return target.toString(); + return addTypeString(target, this); } private Object invoke_V(Object... av) throws Throwable { if (test.invokeExact(av)) @@ -1038,7 +1038,7 @@ public abstract class MethodHandleImpl { return GuardWithTest.make(token, test, target, fallback); } - private static class GuardWithCatch extends JavaMethodHandle { + private static class GuardWithCatch extends BoundMethodHandle { private final MethodHandle target; private final Class exType; private final MethodHandle catcher; @@ -1047,14 +1047,14 @@ public abstract class MethodHandleImpl { } public GuardWithCatch(MethodHandle invoker, MethodHandle target, Class exType, MethodHandle catcher) { - super(invoker); + super(Access.TOKEN, invoker); this.target = target; this.exType = exType; this.catcher = catcher; } @Override public String toString() { - return target.toString(); + return addTypeString(target, this); } private Object invoke_V(Object... av) throws Throwable { try { @@ -1219,21 +1219,24 @@ public abstract class MethodHandleImpl { if (target != null) name = MethodHandleNatives.getMethodName(target); if (name == null) - return ""; - return name.getName(); + return "invoke" + target.type(); + return name.getName() + target.type(); } - public static String addTypeString(MethodHandle target) { - if (target == null) return "null"; - return target.toString() + target.type(); + static String addTypeString(Object obj, MethodHandle target) { + String str = String.valueOf(obj); + if (target == null) return str; + int paren = str.indexOf('('); + if (paren >= 0) str = str.substring(0, paren); + return str + target.type(); } - public static void checkSpreadArgument(Object av, int n) { + static void checkSpreadArgument(Object av, int n) { if (av == null ? n != 0 : ((Object[])av).length != n) throw newIllegalArgumentException("Array is not of length "+n); } - public static void raiseException(int code, Object actual, Object required) { + static void raiseException(int code, Object actual, Object required) { String message; // disregard the identity of the actual object, if it is not a class: if (!(actual instanceof Class) && !(actual instanceof MethodType)) diff --git a/jdk/src/share/classes/sun/dyn/SpreadGeneric.java b/jdk/src/share/classes/sun/dyn/SpreadGeneric.java index 2b12b067666..5ba601b13d7 100644 --- a/jdk/src/share/classes/sun/dyn/SpreadGeneric.java +++ b/jdk/src/share/classes/sun/dyn/SpreadGeneric.java @@ -208,7 +208,7 @@ class SpreadGeneric { * The invoker is kept separate from the target because it can be * generated once per type erasure family, and reused across adapters. */ - static abstract class Adapter extends JavaMethodHandle { + static abstract class Adapter extends BoundMethodHandle { /* * class X<> extends Adapter { * (Object**N)=>R target; @@ -221,21 +221,21 @@ class SpreadGeneric { @Override public String toString() { - return target.toString(); + return MethodHandleImpl.addTypeString(target, this); } static final MethodHandle NO_ENTRY = ValueConversions.identity(); protected boolean isPrototype() { return target == null; } protected Adapter(SpreadGeneric outer) { - super(NO_ENTRY); + super(Access.TOKEN, NO_ENTRY); this.outer = outer; this.target = null; assert(isPrototype()); } protected Adapter(SpreadGeneric outer, MethodHandle target) { - super(outer.entryPoint); + super(Access.TOKEN, outer.entryPoint); this.outer = outer; this.target = target; } diff --git a/jdk/src/share/classes/sun/dyn/ToGeneric.java b/jdk/src/share/classes/sun/dyn/ToGeneric.java index 65acc6f65b0..80e7430dbe6 100644 --- a/jdk/src/share/classes/sun/dyn/ToGeneric.java +++ b/jdk/src/share/classes/sun/dyn/ToGeneric.java @@ -323,7 +323,7 @@ class ToGeneric { * via another method handle {@code convert}, which is responsible for * converting the object result into the raw return value. */ - static abstract class Adapter extends JavaMethodHandle { + static abstract class Adapter extends BoundMethodHandle { /* * class X<> extends Adapter { * Object...=>Object target; @@ -337,13 +337,13 @@ class ToGeneric { @Override public String toString() { - return target == null ? "prototype:"+convert : target.toString(); + return target == null ? "prototype:"+convert : MethodHandleImpl.addTypeString(target, this); } protected boolean isPrototype() { return target == null; } /* Prototype constructor. */ protected Adapter(MethodHandle entryPoint) { - super(entryPoint); + super(Access.TOKEN, entryPoint); this.invoker = null; this.convert = entryPoint; this.target = null; @@ -355,7 +355,7 @@ class ToGeneric { } protected Adapter(MethodHandle entryPoint, MethodHandle invoker, MethodHandle convert, MethodHandle target) { - super(entryPoint); + super(Access.TOKEN, entryPoint); this.invoker = invoker; this.convert = convert; this.target = target; diff --git a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java b/jdk/src/share/classes/sun/dyn/util/ValueConversions.java index aeacb9e0f0f..8cb5ece3967 100644 --- a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java +++ b/jdk/src/share/classes/sun/dyn/util/ValueConversions.java @@ -649,7 +649,9 @@ public class ValueConversions { return mh; } // slow path - MethodType type = MethodType.methodType(wrap.primitiveType(), wrap.primitiveType()); + MethodType type = MethodType.methodType(wrap.primitiveType()); + if (wrap != Wrapper.VOID) + type = type.appendParameterTypes(wrap.primitiveType()); try { mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", type); } catch (NoAccessException ex) { @@ -677,7 +679,7 @@ public class ValueConversions { } private static MethodHandle retype(MethodType type, MethodHandle mh) { - return AdapterMethodHandle.makeRetypeOnly(IMPL_TOKEN, type, mh); + return AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, type, mh); } private static final Object[] NO_ARGS_ARRAY = {}; diff --git a/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java b/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java index 13987dad9a9..0382bea42cd 100644 --- a/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java +++ b/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java @@ -25,7 +25,6 @@ package sun.dyn.util; -import java.dyn.LinkagePermission; import java.dyn.NoAccessException; import java.lang.reflect.Modifier; import sun.dyn.MemberName; @@ -43,6 +42,7 @@ public class VerifyAccess { private static final int PACKAGE_ONLY = 0; private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY); + private static final boolean ALLOW_NESTMATE_ACCESS = false; /** * Evaluate the JVM linkage rules for access to the given method @@ -102,6 +102,8 @@ public class VerifyAccess { // a superclass of the lookup class. } } + if (defc == lookupClass) + return true; // easy check; all self-access is OK switch (mods & ALL_ACCESS_MODES) { case PUBLIC: if (refc != defc) return true; // already checked above @@ -112,7 +114,8 @@ public class VerifyAccess { return isSamePackage(defc, lookupClass); case PRIVATE: // Loosened rules for privates follows access rules for inner classes. - return isSamePackageMember(defc, lookupClass); + return (ALLOW_NESTMATE_ACCESS && + isSamePackageMember(defc, lookupClass)); default: throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods)); } @@ -206,24 +209,4 @@ public class VerifyAccess { } return false; } - - /** - * Ensure the requesting class have privileges to perform invokedynamic - * linkage operations on subjectClass. True if requestingClass is - * Access.class (meaning the request originates from the JVM) or if the - * classes are in the same package and have consistent class loaders. - * (The subject class loader must be identical with or be a child of - * the requesting class loader.) - * @param requestingClass - * @param subjectClass - */ - public static void checkBootstrapPrivilege(Class requestingClass, Class subjectClass, - String permissionName) { - if (requestingClass == null) return; - if (requestingClass == subjectClass) return; - SecurityManager security = System.getSecurityManager(); - if (security == null) return; // open season - if (isSamePackage(requestingClass, subjectClass)) return; - security.checkPermission(new LinkagePermission(permissionName, requestingClass)); - } } diff --git a/jdk/src/share/classes/sun/dyn/util/Wrapper.java b/jdk/src/share/classes/sun/dyn/util/Wrapper.java index 5229c807310..a3e34dd8147 100644 --- a/jdk/src/share/classes/sun/dyn/util/Wrapper.java +++ b/jdk/src/share/classes/sun/dyn/util/Wrapper.java @@ -26,17 +26,19 @@ package sun.dyn.util; public enum Wrapper { - INT(Integer.class, int.class, 'I', (Integer)(int)0, Format.signed(32)), - LONG(Long.class, long.class, 'J', (Long)(long)0, Format.signed(64)), + BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, Format.unsigned(1)), + // These must be in the order defined for widening primitive conversions in JLS 5.1.2 BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, Format.signed(8)), SHORT(Short.class, short.class, 'S', (Short)(short)0, Format.signed(16)), CHAR(Character.class, char.class, 'C', (Character)(char)0, Format.unsigned(16)), - BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, Format.unsigned(1)), + INT(Integer.class, int.class, 'I', (Integer)(int)0, Format.signed(32)), + LONG(Long.class, long.class, 'J', (Long)(long)0, Format.signed(64)), FLOAT(Float.class, float.class, 'F', (Float)(float)0, Format.floating(32)), DOUBLE(Double.class, double.class, 'D', (Double)(double)0, Format.floating(64)), - VOID(Void.class, void.class, 'V', null, Format.other(0)), //NULL(Null.class, null.class, 'N', null, Format.other(1)), OBJECT(Object.class, Object.class, 'L', null, Format.other(1)), + // VOID must be the last type, since it is "assignable" from any other type: + VOID(Void.class, void.class, 'V', null, Format.other(0)), ; private final Class wrapperType; @@ -76,9 +78,11 @@ public enum Wrapper { false); return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT); } - static int + static final int INT = SIGNED | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT), + SHORT = SIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT), BOOLEAN = UNSIGNED | (1 << SIZE_SHIFT) | (1 << SLOT_SHIFT), + CHAR = UNSIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT), FLOAT = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT), VOID = UNSIGNED | (0 << SIZE_SHIFT) | (0 << SLOT_SHIFT), NUM_MASK = (-1) << SIZE_SHIFT; @@ -111,6 +115,29 @@ public enum Wrapper { /** Is the wrapped type either float or double? */ public boolean isFloating() { return format >= Format.FLOAT; } + /** Does the JVM verifier allow a variable of this wrapper's + * primitive type to be assigned from a value of the given wrapper's primitive type? + * Cases: + *

      + *
    • unboxing followed by widening primitive conversion + *
    • any type converted to {@code void} + *
    • boxing conversion followed by widening reference conversion to {@code Object} + *
    • conversion of {@code boolean} to any type + *
    + */ + public boolean isConvertibleFrom(Wrapper source) { + if (this == source) return true; + if (this.compareTo(source) < 0) { + // At best, this is a narrowing conversion. + return false; + } + if ((this.format ^ source.format) == (Format.SHORT ^ Format.CHAR)) { + assert (this == SHORT && source == CHAR) || (this == CHAR && source == SHORT); + return false; + } + return true; + } + /** Produce a zero value for the given wrapper type. * This will be a numeric zero for a number or character, * false for a boolean, and null for a reference or void. @@ -122,10 +149,10 @@ public enum Wrapper { public Object zero() { return zero; } /** Produce a zero value for the given wrapper type T. - * The optinoal argument must a type compatible with this wrapper. + * The optional argument must a type compatible with this wrapper. * Equivalent to {@code this.cast(this.zero(), type)}. */ - public T zero(Class type) { return cast(zero, type); } + public T zero(Class type) { return convert(zero, type); } // /** Produce a wrapper for the given wrapper or primitive type. */ // public static Wrapper valueOf(Class type) { @@ -264,7 +291,11 @@ public enum Wrapper { exampleType.isInterface()) { return forceType(wrapperType, exampleType); } - throw new ClassCastException(exampleType + " not <:" + wrapperType); + throw newClassCastException(exampleType, primitiveType); + } + + private static ClassCastException newClassCastException(Class actual, Class expected) { + return new ClassCastException(actual + " is not compatible with " + expected); } /** If {@code type} is a primitive type, return the corresponding @@ -325,17 +356,55 @@ public enum Wrapper { // } /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type. + * The given target type must be this wrapper's primitive or wrapper type. + * If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check. * Performs standard primitive conversions, including truncation and float conversions. * The given type must be compatible with this wrapper. That is, it must either * be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else * it must be the wrapper's primitive type. + * Primitive conversions are only performed if the given type is itself a primitive. * @throws ClassCastException if the given type is not compatible with this wrapper */ public T cast(Object x, Class type) { + return convert(x, type, true); + } + + /** Convert a wrapped value to the given type. + * The given target type must be this wrapper's primitive or wrapper type. + * This is equivalent to {@link #cast}, except that it refuses to perform + * narrowing primitive conversions. + */ + public T convert(Object x, Class type) { + return convert(x, type, false); + } + + private T convert(Object x, Class type, boolean isCast) { + if (this == OBJECT) { + // If the target wrapper is OBJECT, just do a reference cast. + // If the target type is an interface, perform no runtime check. + // (This loophole is safe, and is allowed by the JVM verifier.) + // If the target type is a primitive, change it to a wrapper. + @SuppressWarnings("unchecked") + T result = (T) x; // unchecked warning is expected here + return result; + } Class wtype = wrapperType(type); - if (wtype.isInstance(x)) - return wtype.cast(x); - return wtype.cast(wrap(x)); + if (wtype.isInstance(x)) { + @SuppressWarnings("unchecked") + T result = (T) x; // unchecked warning is expected here + return result; + } + Class sourceType = x.getClass(); // throw NPE if x is null + if (!isCast) { + Wrapper source = findWrapperType(sourceType); + if (source == null || !this.isConvertibleFrom(source)) { + throw newClassCastException(wtype, sourceType); + } + } + @SuppressWarnings("unchecked") + T result = (T) wrap(x); // unchecked warning is expected here + assert result.getClass() == wtype; + return result; } /** Cast a reference type to another reference type. diff --git a/jdk/test/java/dyn/InvokeGenericTest.java b/jdk/test/java/dyn/InvokeGenericTest.java index 83aa10b0202..1b20d95ea61 100644 --- a/jdk/test/java/dyn/InvokeGenericTest.java +++ b/jdk/test/java/dyn/InvokeGenericTest.java @@ -398,7 +398,7 @@ public class InvokeGenericTest { case 4: junk = target.invokeGeneric(args[0], args[1], args[2], args[3]); break; default: - junk = MethodHandles.invokeVarargs(target, args); break; + junk = target.invokeWithArguments(args); break; } } catch (WrongMethodTypeException ex) { return; diff --git a/jdk/test/java/dyn/JavaDocExamples.java b/jdk/test/java/dyn/JavaDocExamplesTest.java similarity index 57% rename from jdk/test/java/dyn/JavaDocExamples.java rename to jdk/test/java/dyn/JavaDocExamplesTest.java index db5a5ef2a21..90290c60da6 100644 --- a/jdk/test/java/dyn/JavaDocExamples.java +++ b/jdk/test/java/dyn/JavaDocExamplesTest.java @@ -25,18 +25,18 @@ /* @test * @summary example code used in javadoc for java.dyn API - * @compile -XDallowTransitionalJSR292=no JavaDocExamples.java - * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.JavaDocExamples + * @compile -XDallowTransitionalJSR292=no JavaDocExamplesTest.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.JavaDocExamplesTest */ /* ---- To run outside jtreg: $ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \ - $DAVINCI/sources/jdk/test/java/dyn/JavaDocExamples.java + $DAVINCI/sources/jdk/test/java/dyn/JavaDocExamplesTest.java $ $JAVA7X_HOME/bin/java -cp $JUNIT4_JAR:/tmp/Classes \ -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \ - -Dtest.java.dyn.JavaDocExamples.verbosity=1 \ - test.java.dyn.JavaDocExamples + -Dtest.java.dyn.JavaDocExamplesTest.verbosity=1 \ + test.java.dyn.JavaDocExamplesTest ---- */ @@ -57,15 +57,15 @@ import static org.junit.Assume.*; /** * @author jrose */ -public class JavaDocExamples { +public class JavaDocExamplesTest { /** Wrapper for running the JUnit tests in this module. * Put JUnit on the classpath! */ public static void main(String... ignore) { - org.junit.runner.JUnitCore.runClasses(JavaDocExamples.class); + org.junit.runner.JUnitCore.runClasses(JavaDocExamplesTest.class); } // How much output? - static int verbosity = Integer.getInteger("test.java.dyn.JavaDocExamples.verbosity", 0); + static int verbosity = Integer.getInteger("test.java.dyn.JavaDocExamplesTest.verbosity", 0); {} static final private Lookup LOOKUP = lookup(); @@ -120,9 +120,79 @@ assertEquals("xz", /*(String)*/ d12.invokeExact("x", 12, true, "z")); }} } + @Test public void testFilterArguments() throws Throwable { + {{ +{} /// JAVADOC +MethodHandle cat = lookup().findVirtual(String.class, + "concat", methodType(String.class, String.class)); +cat = cat.asType(methodType(Object.class, String.class, String.class)); /*(String)*/ +MethodHandle upcase = lookup().findVirtual(String.class, + "toUpperCase", methodType(String.class)); +assertEquals("xy", /*(String)*/ cat.invokeExact("x", "y")); // xy +MethodHandle f0 = filterArguments(cat, 0, upcase); +assertEquals("Xy", /*(String)*/ f0.invokeExact("x", "y")); // Xy +MethodHandle f1 = filterArguments(cat, 1, upcase); +assertEquals("xY", /*(String)*/ f1.invokeExact("x", "y")); // xY +MethodHandle f2 = filterArguments(cat, 0, upcase, upcase); +assertEquals("XY", /*(String)*/ f2.invokeExact("x", "y")); // XY + }} + } + static void assertEquals(Object exp, Object act) { if (verbosity > 0) System.out.println("result: "+act); Assert.assertEquals(exp, act); } + + @Test public void testVolatileCallSite() throws Throwable { + {{ +{} /// JAVADOC +MethodHandle strcat = MethodHandles.lookup() + .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class)); +MethodHandle trueCon = MethodHandles.constant(boolean.class, true); +MethodHandle falseCon = MethodHandles.constant(boolean.class, false); +VolatileCallSite switcher = new VolatileCallSite(trueCon, falseCon); +// following steps may be repeated to re-use the same switcher: +MethodHandle worker1 = strcat; +MethodHandle worker2 = MethodHandles.permuteArguments(strcat, strcat.type(), 1, 0); +MethodHandle worker = MethodHandles.guardWithTest(switcher.dynamicInvoker(), worker1, worker2); +System.out.println((String) worker.invokeExact("met", "hod")); // method +switcher.invalidate(); +System.out.println((String) worker.invokeExact("met", "hod")); // hodmet + }} + } + +static MethodHandle asList; + @Test public void testWithTypeHandler() throws Throwable { + {{ +{} /// JAVADOC +MethodHandle makeEmptyList = MethodHandles.constant(List.class, Arrays.asList()); +MethodHandle asList = lookup() + .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class)); + +JavaDocExamplesTest.asList = asList; +/* +static MethodHandle collectingTypeHandler(MethodHandle base, MethodType newType) { + return asList.asCollector(Object[].class, newType.parameterCount()).asType(newType); +} +*/ + +MethodHandle collectingTypeHandler = lookup() + .findStatic(lookup().lookupClass(), "collectingTypeHandler", + methodType(MethodHandle.class, MethodHandle.class, MethodType.class)); +MethodHandle makeAnyList = makeEmptyList.withTypeHandler(collectingTypeHandler); + +System.out.println(makeAnyList.invokeGeneric()); +System.out.println(makeAnyList.invokeGeneric(1)); +System.out.println(makeAnyList.invokeGeneric("two", "too")); + }} + } + +static MethodHandle collectingTypeHandler(MethodHandle base, MethodType newType) { + //System.out.println("Converting "+asList+" to "+newType); + MethodHandle conv = asList.asCollector(Object[].class, newType.parameterCount()).asType(newType); + //System.out.println(" =>"+conv); + return conv; +} + } diff --git a/jdk/test/java/dyn/MethodHandlesTest.java b/jdk/test/java/dyn/MethodHandlesTest.java index 6986390c72e..6a80775bf3d 100644 --- a/jdk/test/java/dyn/MethodHandlesTest.java +++ b/jdk/test/java/dyn/MethodHandlesTest.java @@ -62,7 +62,6 @@ public class MethodHandlesTest { // lookups, without exercising the actual method handle. static boolean DO_MORE_CALLS = true; - @Test public void testFirst() throws Throwable { verbosity += 9; try { @@ -458,7 +457,7 @@ public class MethodHandlesTest { Exception noAccess = null; try { if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); - target = lookup.findStatic(defc, name, type); + target = lookup.in(defc).findStatic(defc, name, type); } catch (NoAccessException ex) { noAccess = ex; } @@ -469,16 +468,22 @@ public class MethodHandlesTest { assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); if (!positive) return; // negative test failed as expected assertEquals(type, target.type()); - assertTrue(target.toString().contains(name)); // rough check + assertNameStringContains(target, name); if (!DO_MORE_CALLS && lookup != PRIVATE) return; Object[] args = randomArgs(params); printCalled(target, name, args); - target.invokeVarargs(args); + target.invokeWithArguments(args); assertCalled(name, args); if (verbosity >= 1) System.out.print(':'); } + // rough check of name string + static void assertNameStringContains(Object x, String s) { + if (x.toString().contains(s)) return; + assertEquals(s, x); + } + @Test public void testFindVirtual() throws Throwable { if (CAN_SKIP_WORKING) return; @@ -522,7 +527,7 @@ public class MethodHandlesTest { Exception noAccess = null; try { if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); - target = lookup.findVirtual(defc, methodName, type); + target = lookup.in(defc).findVirtual(defc, methodName, type); } catch (NoAccessException ex) { noAccess = ex; } @@ -535,12 +540,12 @@ public class MethodHandlesTest { Class[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); assertEquals(typeWithSelf, target.type()); - assertTrue(target.toString().contains(methodName)); // rough check + assertNameStringContains(target, methodName); if (!DO_MORE_CALLS && lookup != PRIVATE) return; Object[] argsWithSelf = randomArgs(paramsWithSelf); if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc); printCalled(target, name, argsWithSelf); - target.invokeVarargs(argsWithSelf); + target.invokeWithArguments(argsWithSelf); assertCalled(name, argsWithSelf); if (verbosity >= 1) System.out.print(':'); @@ -576,7 +581,8 @@ public class MethodHandlesTest { Exception noAccess = null; try { if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); - target = lookup.findSpecial(defc, name, type, specialCaller); + if (verbosity >= 5) System.out.println(" lookup => "+lookup.in(specialCaller)); + target = lookup.in(specialCaller).findSpecial(defc, name, type, specialCaller); } catch (NoAccessException ex) { noAccess = ex; } @@ -591,11 +597,11 @@ public class MethodHandlesTest { assertEquals(type, target.type().dropParameterTypes(0,1)); Class[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params); MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); - assertTrue(target.toString().contains(name)); // rough check + assertNameStringContains(target, name); if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE) return; Object[] args = randomArgs(paramsWithSelf); printCalled(target, name, args); - target.invokeVarargs(args); + target.invokeWithArguments(args); assertCalled(name, args); } @@ -632,7 +638,7 @@ public class MethodHandlesTest { Exception noAccess = null; try { if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); - target = lookup.bind(receiver, methodName, type); + target = lookup.in(defc).bind(receiver, methodName, type); } catch (NoAccessException ex) { noAccess = ex; } @@ -645,7 +651,7 @@ public class MethodHandlesTest { assertEquals(type, target.type()); Object[] args = randomArgs(params); printCalled(target, name, args); - target.invokeVarargs(args); + target.invokeWithArguments(args); Object[] argsWithReceiver = cat(array(Object[].class, receiver), args); assertCalled(name, argsWithReceiver); if (verbosity >= 1) @@ -705,9 +711,9 @@ public class MethodHandlesTest { try { if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); if (isSpecial) - target = lookup.unreflectSpecial(rmethod, specialCaller); + target = lookup.in(specialCaller).unreflectSpecial(rmethod, specialCaller); else - target = lookup.unreflect(rmethod); + target = lookup.in(defc).unreflect(rmethod); } catch (NoAccessException ex) { noAccess = ex; } @@ -737,7 +743,7 @@ public class MethodHandlesTest { } Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf); printCalled(target, name, argsMaybeWithSelf); - target.invokeVarargs(argsMaybeWithSelf); + target.invokeWithArguments(argsMaybeWithSelf); assertCalled(name, argsMaybeWithSelf); if (verbosity >= 1) System.out.print(':'); @@ -875,7 +881,7 @@ public class MethodHandlesTest { if (isStatic) expType = expType.dropParameterTypes(0, 1); MethodHandle mh = lookup.unreflectGetter(f); assertSame(mh.type(), expType); - assertEquals(mh.toString(), fname); + assertNameStringContains(mh, fname); HasFields fields = new HasFields(); Object sawValue; Class rtype = type; @@ -947,7 +953,7 @@ public class MethodHandlesTest { mh = lookup.findStaticSetter(fclass, fname, ftype); else throw new InternalError(); assertSame(mh.type(), expType); - assertEquals(mh.toString(), fname); + assertNameStringContains(mh, fname); HasFields fields = new HasFields(); Object sawValue; Class vtype = type; @@ -1102,6 +1108,18 @@ public class MethodHandlesTest { } } + static MethodHandle typeHandler2(MethodHandle target, MethodType newType) { + MethodType oldType = target.type(); + int oldArity = oldType.parameterCount(); + int newArity = newType.parameterCount(); + if (newArity < oldArity) + return MethodHandles.insertArguments(target, oldArity, "OPTIONAL"); + else if (newArity > oldArity) + return MethodHandles.dropArguments(target, oldArity-1, newType.parameterType(oldArity-1)); + else + return target; // attempt no further conversions + } + @Test public void testConvertArguments() throws Throwable { if (CAN_SKIP_WORKING) return; @@ -1115,10 +1133,29 @@ public class MethodHandlesTest { } void testConvert(MethodHandle id, Class rtype, String name, Class... params) throws Throwable { - testConvert(true, id, rtype, name, params); + testConvert(true, false, id, rtype, name, params); + testConvert(true, true, id, rtype, name, params); } - void testConvert(boolean positive, MethodHandle id, Class rtype, String name, Class... params) throws Throwable { + @Test + public void testTypeHandler() throws Throwable { + MethodHandle id = Callee.ofType(1); + MethodHandle th2 = PRIVATE.findStatic(MethodHandlesTest.class, "typeHandler2", + MethodType.methodType(MethodHandle.class, MethodHandle.class, MethodType.class)); + MethodHandle id2 = id.withTypeHandler(th2); + testConvert(true, false, id2, null, "id", Object.class); + testConvert(true, true, id2, null, "id", Object.class); + if (true) return; //FIXME + testConvert(true, false, id2, null, "id", String.class); // FIXME: throws WMT + testConvert(false, true, id2, null, "id", String.class); // FIXME: should not succeed + testConvert(false, false, id2, null, "id", Object.class, String.class); //FIXME: array[1] line 1164 + testConvert(true, true, id2, null, "id", Object.class, String.class); + testConvert(false, false, id2, null, "id"); + testConvert(true, true, id2, null, "id"); + } + + void testConvert(boolean positive, boolean useAsType, + MethodHandle id, Class rtype, String name, Class... params) throws Throwable { countTest(positive); MethodType idType = id.type(); if (rtype == null) rtype = idType.returnType(); @@ -1135,7 +1172,7 @@ public class MethodHandlesTest { if (src != dst) convArgs[i] = castToWrapper(convArgs[i], dst); } - Object convResult = id.invokeVarargs(convArgs); + Object convResult = id.invokeWithArguments(convArgs); { Class dst = newType.returnType(); Class src = idType.returnType(); @@ -1145,7 +1182,10 @@ public class MethodHandlesTest { MethodHandle target = null; RuntimeException error = null; try { - target = MethodHandles.convertArguments(id, newType); + if (useAsType) + target = MethodHandles.convertArguments(id, newType); + else + target = id.asType(newType); } catch (RuntimeException ex) { error = ex; } @@ -1157,7 +1197,7 @@ public class MethodHandlesTest { if (!positive) return; // negative test failed as expected assertEquals(newType, target.type()); printCalled(target, id.toString(), args); - Object result = target.invokeVarargs(args); + Object result = target.invokeWithArguments(args); assertCalled(name, convArgs); assertEquals(convResult, result); if (verbosity >= 1) @@ -1279,7 +1319,7 @@ public class MethodHandlesTest { MethodType outType = MethodType.methodType(Object.class, permTypes); MethodHandle target = MethodHandles.convertArguments(ValueConversions.varargsList(outargs), outType); MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder); - Object result = newTarget.invokeVarargs(args); + Object result = newTarget.invokeWithArguments(args); Object expected = Arrays.asList(permArgs); assertEquals(expected, result); } @@ -1311,7 +1351,7 @@ public class MethodHandlesTest { Object[] args = randomArgs(target2.type().parameterArray()); // make sure the target does what we think it does: if (pos == 0 && nargs < 5) { - Object[] check = (Object[]) target.invokeVarargs(args); + Object[] check = (Object[]) target.invokeWithArguments(args); assertArrayEquals(args, check); switch (nargs) { case 0: @@ -1342,7 +1382,7 @@ public class MethodHandlesTest { } else { Object[] args1 = Arrays.copyOfRange(args, 0, pos+1); args1[pos] = Arrays.copyOfRange(args, pos, args.length); - returnValue = (Object[]) result.invokeVarargs(args1); + returnValue = (Object[]) result.invokeWithArguments(args1); } assertArrayEquals(args, returnValue); } @@ -1379,7 +1419,7 @@ public class MethodHandlesTest { if (verbosity >= 3) System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]"); MethodHandle result = MethodHandles.collectArguments(target, newType); - Object[] returnValue = (Object[]) result.invokeVarargs(args); + Object[] returnValue = (Object[]) result.invokeWithArguments(args); // assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]); // returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]); // collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]); @@ -1412,7 +1452,7 @@ public class MethodHandlesTest { MethodHandle target2 = MethodHandles.insertArguments(target, pos, (Object[]) argsToInsert.toArray()); argsToInsert.clear(); // remove from argsToInsert - Object res2 = target2.invokeVarargs(argsToPass); + Object res2 = target2.invokeWithArguments(argsToPass); Object res2List = Arrays.asList((Object[])res2); if (verbosity >= 3) System.out.println("result: "+res2List); @@ -1440,14 +1480,12 @@ public class MethodHandlesTest { Object[] argsToPass = randomArgs(nargs, Object.class); if (verbosity >= 3) System.out.println("filter "+target+" at "+pos+" with "+filter); - MethodHandle[] filters = new MethodHandle[pos*2+1]; - filters[pos] = filter; - MethodHandle target2 = MethodHandles.filterArguments(target, filters); + MethodHandle target2 = MethodHandles.filterArguments(target, pos, filter); // Simulate expected effect of filter on arglist: Object[] filteredArgs = argsToPass.clone(); filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]); List expected = Arrays.asList(filteredArgs); - Object result = target2.invokeVarargs(argsToPass); + Object result = target2.invokeWithArguments(argsToPass); if (verbosity >= 3) System.out.println("result: "+result); if (!expected.equals(result)) @@ -1482,9 +1520,9 @@ public class MethodHandlesTest { List argsToFold = expected.subList(pos, pos + fold); if (verbosity >= 3) System.out.println("fold: "+argsToFold+" into "+target2); - Object foldedArgs = combine.invokeVarargs(argsToFold); + Object foldedArgs = combine.invokeWithArguments(argsToFold); argsToFold.add(0, foldedArgs); - Object result = target2.invokeVarargs(argsToPass); + Object result = target2.invokeWithArguments(argsToPass); if (verbosity >= 3) System.out.println("result: "+result); if (!expected.equals(result)) @@ -1516,7 +1554,7 @@ public class MethodHandlesTest { for (int i = drop; i > 0; i--) { argsToDrop.add(pos, "blort#"+i); } - Object res2 = target2.invokeVarargs(argsToDrop); + Object res2 = target2.invokeWithArguments(argsToDrop); Object res2List = Arrays.asList((Object[])res2); //if (!resList.equals(res2List)) // System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List); @@ -1572,7 +1610,7 @@ public class MethodHandlesTest { countTest(); calledLog.clear(); inv = MethodHandles.exactInvoker(type); - result = inv.invokeVarargs(targetPlusArgs); + result = inv.invokeWithArguments(targetPlusArgs); if (testRetCode) assertEquals(code, result); assertCalled("invokee", args); // generic invoker @@ -1598,7 +1636,7 @@ public class MethodHandlesTest { assertCalled("invokee", args); } calledLog.clear(); - result = inv.invokeVarargs(targetPlusArgs); + result = inv.invokeWithArguments(targetPlusArgs); if (testRetCode) assertEquals(code, result); assertCalled("invokee", args); // varargs invoker #0 @@ -1640,17 +1678,29 @@ public class MethodHandlesTest { List tailList = targetPlusVarArgs.subList(1+k, 1+nargs); Object[] tail = tailList.toArray(); tailList.clear(); tailList.add(tail); - result = inv.invokeVarargs(targetPlusVarArgs); + result = inv.invokeWithArguments(targetPlusVarArgs); if (testRetCode) assertEquals(code, result); assertCalled("invokee", args); } + // dynamic invoker countTest(); - CallSite site = new CallSite(MethodHandlesTest.class, "foo", type); + CallSite site = new CallSite(type); inv = MethodHandles.dynamicInvoker(site); + + // see if we get the result of the original target: + try { + result = inv.invokeWithArguments(args); + assertTrue("should not reach here", false); + } catch (IllegalStateException ex) { + String msg = ex.getMessage(); + assertTrue(msg, msg.contains("site")); + } + + // set new target after invoker is created, to make sure we track target site.setTarget(target); calledLog.clear(); - result = inv.invokeVarargs(args); + result = inv.invokeWithArguments(args); if (testRetCode) assertEquals(code, result); assertCalled("invokee", args); } @@ -1734,7 +1784,7 @@ public class MethodHandlesTest { String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals"); if (verbosity >= 3) System.out.println(logEntry(willCall, argList)); - Object result = mh.invokeVarargs(argList); + Object result = mh.invokeWithArguments(argList); assertCalled(willCall, argList); } } @@ -1776,7 +1826,7 @@ public class MethodHandlesTest { //System.out.println("catching with "+target+" : "+throwOrReturn); Object[] args = randomArgs(nargs, Object.class); args[1] = (throwIt ? thrown : null); - Object returned = target.invokeVarargs(args); + Object returned = target.invokeWithArguments(args); //System.out.println("return from "+target+" : "+returned); if (!throwIt) { assertSame(args[0], returned); @@ -1828,13 +1878,10 @@ public class MethodHandlesTest { testCastFailure("unbox/return", 11000); } - static class Surprise implements MethodHandleProvider { + static class Surprise { public MethodHandle asMethodHandle() { return VALUE.bindTo(this); } - public MethodHandle asMethodHandle(MethodType type) { - return asMethodHandle().asType(type); - } Object value(Object x) { trace("value", x); if (boo != null) return boo; @@ -1896,8 +1943,8 @@ public class MethodHandlesTest { } if (callee != null) { callee = MethodHandles.convertArguments(callee, MethodType.genericMethodType(1)); - surprise = MethodHandles.filterArguments(callee, surprise); - identity = MethodHandles.filterArguments(callee, identity); + surprise = MethodHandles.filterArguments(callee, 0, surprise); + identity = MethodHandles.filterArguments(callee, 0, identity); } } assertNotSame(mode, surprise, surprise0); @@ -1949,7 +1996,7 @@ public class MethodHandlesTest { assertEquals(mt, mh.type()); assertEquals(Example.class, mh.type().returnType()); args = randomArgs(mh.type().parameterArray()); - mh.invokeVarargs(args); + mh.invokeWithArguments(args); assertCalled(name, args); // Try a virtual method. @@ -1959,7 +2006,7 @@ public class MethodHandlesTest { assertEquals(mt, mh.type().dropParameterTypes(0,1)); assertTrue(mh.type().parameterList().contains(Example.class)); args = randomArgs(mh.type().parameterArray()); - mh.invokeVarargs(args); + mh.invokeWithArguments(args); assertCalled(name, args); } From b44ef9738feab80a161a2d3018b2857b8141367c Mon Sep 17 00:00:00 2001 From: Sunita Koppar Date: Sun, 21 Nov 2010 21:47:49 -0800 Subject: [PATCH 008/139] 6980681: CORBA deadlock in Java SE beleived to be related to CR 6238477 Also reviewed by ken.cavanaugh@oracle.com Reviewed-by: poonam --- .../com/sun/corba/se/impl/orb/ORBImpl.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java index e8aac1da709..bcbdf872651 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,7 +245,14 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB // All access to resolver, localResolver, and urlOperation must be protected using // resolverLock. Do not hold the ORBImpl lock while accessing // resolver, or deadlocks may occur. - private Object resolverLock ; + // Note that we now have separate locks for each resolver type. This is due + // to bug 6980681 and 6238477, which was caused by a deadlock while resolving a + // corbaname: URL that contained a reference to the same ORB as the + // ORB making the call to string_to_object. This caused a deadlock between the + // client thread holding the single lock for access to the urlOperation, + // and the server thread handling the client is_a request waiting on the + // same lock to access the localResolver. + // Used for resolver_initial_references and list_initial_services private Resolver resolver ; @@ -255,8 +262,14 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB // Converts strings to object references for resolvers and string_to_object private Operation urlOperation ; + private final Object urlOperationLock = new java.lang.Object() ; private CorbaServerRequestDispatcher insNamingDelegate ; + // resolverLock must be used for all access to either resolver or + // localResolver, since it is possible for the resolver to indirectly + // refer to the localResolver. Also used to protect access to + // insNamingDelegate. + private final Object resolverLock = new Object() ; private TaggedComponentFactoryFinder taggedComponentFactoryFinder ; @@ -396,7 +409,6 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB } }; - resolverLock = new java.lang.Object() ; requestDispatcherRegistry = new RequestDispatcherRegistryImpl( this, ORBConstants.DEFAULT_SCID); @@ -832,7 +844,7 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB if (str == null) throw wrapper.nullParam() ; - synchronized (resolverLock) { + synchronized (urlOperationLock) { org.omg.CORBA.Object obj = (org.omg.CORBA.Object)op.operate( str ) ; return obj ; } @@ -1773,7 +1785,7 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB */ public void setURLOperation( Operation stringToObject ) { - synchronized (resolverLock) { + synchronized (urlOperationLock) { urlOperation = stringToObject ; } } @@ -1783,7 +1795,7 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB */ public Operation getURLOperation() { - synchronized (resolverLock) { + synchronized (urlOperationLock) { return urlOperation ; } } From a296bc0a0a6f7dd75b86fbe16f700996671aa067 Mon Sep 17 00:00:00 2001 From: Andrew John Hughes Date: Tue, 23 Nov 2010 02:17:23 +0000 Subject: [PATCH 009/139] 7000225: Sanity check on sane-alsa-headers is broken Fix use of tab separators, ${alsa_version} expansion and conditional Reviewed-by: ohair --- jdk/make/common/shared/Sanity.gmk | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/jdk/make/common/shared/Sanity.gmk b/jdk/make/common/shared/Sanity.gmk index 39f99ae7c17..6b545159d54 100644 --- a/jdk/make/common/shared/Sanity.gmk +++ b/jdk/make/common/shared/Sanity.gmk @@ -1389,20 +1389,21 @@ ifdef REQUIRED_ALSA_VERSION endif sane-alsa-headers: ifdef REQUIRED_ALSA_VERSION - if [ "$(ALSA_CHECK)" != "same" -a "$(ALSA_CHECK)" != "newer" ] ; then \ - $(ECHO) "ERROR: The ALSA version must be $(REQUIRED_ALSA_VERSION) or higher. \n" \ - " You have the following ALSA version installed: $${alsa_version) \n" \ - " Please reinstall ALSA (drivers and lib). You can download \n" \ - " the source distribution from http://www.alsa-project.org \n" \ - " or go to http://www.freshrpms.net/docs/alsa/ for precompiled RPM packages. \n" \ - "" >> $(ERROR_FILE) ; \ - fi \ + @if [ "$(ALSA_CHECK)" != "missing" ] ; then \ + if [ "$(ALSA_CHECK)" != "same" -a "$(ALSA_CHECK)" != "newer" ] ; then \ + $(ECHO) "ERROR: The ALSA version must be $(REQUIRED_ALSA_VERSION) or higher. \n" \ + " You have the following ALSA version installed: $${alsa_version} \n" \ + " Please reinstall ALSA (drivers and lib). You can download \n" \ + " the source distribution from http://www.alsa-project.org \n" \ + " or go to http://www.freshrpms.net/docs/alsa/ for precompiled RPM packages. \n" \ + "" >> $(ERROR_FILE) ; \ + fi ; \ else \ - $(ECHO) "ERROR: You seem to not have installed ALSA $(REQUIRED_ALSA_VERSION) or higher. \n" \ - " Please install ALSA (drivers and lib). You can download the \n" \ - " source distribution from http://www.alsa-project.org or go to \n" \ - " http://www.freshrpms.net/docs/alsa/ for precompiled RPM packages. \n" \ - "" >> $(ERROR_FILE) ; \ + $(ECHO) "ERROR: You seem to not have installed ALSA $(REQUIRED_ALSA_VERSION) or higher. \n" \ + " Please install ALSA (drivers and lib). You can download the \n" \ + " source distribution from http://www.alsa-project.org or go to \n" \ + " http://www.freshrpms.net/docs/alsa/ for precompiled RPM packages. \n" \ + "" >> $(ERROR_FILE) ; \ fi endif From aa7f1cc82657b210b84845dd6007a75121c40de2 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Mon, 22 Nov 2010 22:41:31 -0800 Subject: [PATCH 010/139] 6979327: method handle invocation should use casts instead of type parameters to specify return type Change result type parameters to result type casts. (Also, replace private placeholder class InvokeDynamic.) Reviewed-by: twisti --- jdk/make/java/dyn/Makefile | 6 +- .../share/classes/java/dyn/InvokeDynamic.java | 33 ++++ .../share/classes/java/dyn/MethodHandle.java | 8 +- .../classes/sun/dyn/AdapterMethodHandle.java | 2 +- .../share/classes/sun/dyn/CallSiteImpl.java | 4 +- .../share/classes/sun/dyn/FilterGeneric.java | 48 +++--- .../share/classes/sun/dyn/FromGeneric.java | 138 ++++++++--------- .../classes/sun/dyn/MethodHandleImpl.java | 120 +++++++-------- .../share/classes/sun/dyn/SpreadGeneric.java | 142 +++++++++--------- jdk/src/share/classes/sun/dyn/ToGeneric.java | 56 +++---- jdk/test/java/dyn/InvokeGenericTest.java | 6 +- jdk/test/java/dyn/JavaDocExamplesTest.java | 10 +- jdk/test/java/dyn/MethodHandlesTest.java | 39 ++--- 13 files changed, 324 insertions(+), 288 deletions(-) create mode 100644 jdk/src/share/classes/java/dyn/InvokeDynamic.java diff --git a/jdk/make/java/dyn/Makefile b/jdk/make/java/dyn/Makefile index af7bec9d24f..a85b5168126 100644 --- a/jdk/make/java/dyn/Makefile +++ b/jdk/make/java/dyn/Makefile @@ -36,9 +36,7 @@ AUTO_FILES_JAVA_DIRS = java/dyn sun/dyn LANGUAGE_VERSION = -source 7 CLASS_VERSION = -target 7 -# Actually, it will be less disruptive to compile with the same -# -target option as the rest of the system, and just turn on -# the specific compiler option we need here: -OTHER_JAVACFLAGS = -XDinvokedynamic +# Tell the compiler not to accept transitional forms. +OTHER_JAVACFLAGS = -XDallowTransitionalJSR292=no include $(BUILDDIR)/common/Classes.gmk diff --git a/jdk/src/share/classes/java/dyn/InvokeDynamic.java b/jdk/src/share/classes/java/dyn/InvokeDynamic.java new file mode 100644 index 00000000000..9c3ede1ee36 --- /dev/null +++ b/jdk/src/share/classes/java/dyn/InvokeDynamic.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.dyn; + +/** + * This is a place-holder class. Some HotSpot implementations need to see it. + */ +final class InvokeDynamic { + private InvokeDynamic() { throw new InternalError(); } // do not instantiate +} diff --git a/jdk/src/share/classes/java/dyn/MethodHandle.java b/jdk/src/share/classes/java/dyn/MethodHandle.java index 1aec36e27b0..842ae9fa5d4 100644 --- a/jdk/src/share/classes/java/dyn/MethodHandle.java +++ b/jdk/src/share/classes/java/dyn/MethodHandle.java @@ -164,7 +164,7 @@ MethodHandles.Lookup lookup = MethodHandles.lookup(); mt = MethodType.methodType(String.class, char.class, char.class); mh = lookup.findVirtual(String.class, "replace", mt); // (Ljava/lang/String;CC)Ljava/lang/String; -s = mh.<String>invokeExact("daddy",'d','n'); +s = (String) mh.invokeExact("daddy",'d','n'); assert(s.equals("nanny")); // weakly typed invocation (using MHs.invoke) s = (String) mh.invokeWithArguments("sappy", 'p', 'v'); @@ -183,7 +183,7 @@ assert(x.equals(java.util.Arrays.asList(1,2,3))); mt = MethodType.methodType(int.class); mh = lookup.findVirtual(java.util.List.class, "size", mt); // (Ljava/util/List;)I -i = mh.<int>invokeExact(java.util.Arrays.asList(1,2,3)); +i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3)); assert(i == 3); * * Each of the above calls generates a single invokevirtual instruction @@ -298,7 +298,7 @@ public abstract class MethodHandle * @throws WrongMethodTypeException if the target's type is not identical with the caller's type signature * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call */ - public final native @PolymorphicSignature R invokeExact(A... args) throws Throwable; + public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable; /** * Invoke the method handle, allowing any caller signature, @@ -327,7 +327,7 @@ public abstract class MethodHandle * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type signature * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call */ - public final native @PolymorphicSignature R invokeGeneric(A... args) throws Throwable; + public final native @PolymorphicSignature Object invokeGeneric(Object... args) throws Throwable; /** * Perform a varargs invocation, passing the arguments in the given array diff --git a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java b/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java index 06a24faba49..c23699b948c 100644 --- a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java +++ b/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java @@ -496,7 +496,7 @@ public class AdapterMethodHandle extends BoundMethodHandle { if (this.type() == newType) return this; try { - MethodHandle retyped = (MethodHandle) typeHandler.invokeExact(target, newType); + MethodHandle retyped = (MethodHandle) typeHandler.invokeExact(target, newType); // Contract: Must return the desired type, or throw WMT if (retyped.type() != newType) throw new WrongMethodTypeException(retyped.toString()); diff --git a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java index f9bea6d5486..eb5abf74882 100644 --- a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java +++ b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java @@ -78,8 +78,8 @@ public class CallSiteImpl { } else { throw new ClassCastException("bootstrap method failed to produce a MethodHandle or CallSite"); } - PRIVATE_INITIALIZE_CALL_SITE.invokeExact(site, name, type, - callerMethod, callerBCI); + PRIVATE_INITIALIZE_CALL_SITE.invokeExact(site, name, type, + callerMethod, callerBCI); assert(site.getTarget() != null); assert(site.getTarget().type().equals(type)); } catch (Throwable ex) { diff --git a/jdk/src/share/classes/sun/dyn/FilterGeneric.java b/jdk/src/share/classes/sun/dyn/FilterGeneric.java index 1eaf34d5a13..b593588c6e9 100644 --- a/jdk/src/share/classes/sun/dyn/FilterGeneric.java +++ b/jdk/src/share/classes/sun/dyn/FilterGeneric.java @@ -303,7 +303,7 @@ class FilterGeneric { protected Object invoke_C0(Object a0) { return target.invokeExact(filter.invokeExact(a0)); } protected Object invoke_C1(Object a0) { return target.invokeExact(a0, filter.invokeExact()); } protected Object invoke_Y0(Object a0) { Object[] av = { a0 }; - filter.invokeExact(av); return target.invokeExact(av[0]); } + filter.invokeExact(av); return target.invokeExact(av[0]); } } static class F2X extends Adapter { protected F2X(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -320,7 +320,7 @@ class FilterGeneric { protected Object invoke_C1(Object a0, Object a1) { return target.invokeExact(a0, filter.invokeExact(a1)); } protected Object invoke_C2(Object a0, Object a1) { return target.invokeExact(a0, a1, filter.invokeExact()); } protected Object invoke_Y0(Object a0, Object a1) { Object[] av = { a0, a1 }; - filter.invokeExact(av); return target.invokeExact(av[0], av[1]); } + filter.invokeExact(av); return target.invokeExact(av[0], av[1]); } } // */ @@ -337,7 +337,7 @@ class FilterGeneric { return target.invokeExact(filter.invokeExact()); } static final Object[] NO_ARGS = { }; protected Object invoke_Y0() throws Throwable { - filter.invokeExact(NO_ARGS); // make the flyby + filter.invokeExact(NO_ARGS); // make the flyby return target.invokeExact(); } } @@ -375,7 +375,7 @@ class genclasses { " return target.invokeExact(@av@, filter.invokeExact()); }", " protected Object invoke_Y0(@Tvav@) throws Throwable {", " Object[] av = { @av@ };", - " filter.invokeExact(av); // make the flyby", + " filter.invokeExact(av); // make the flyby", " return target.invokeExact(@av[i]@); }", " }", } }; @@ -518,7 +518,7 @@ class genclasses { return target.invokeExact(a0, filter.invokeExact()); } protected Object invoke_Y0(Object a0) throws Throwable { Object[] av = { a0 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0]); } } static class F2 extends Adapter { @@ -548,7 +548,7 @@ class genclasses { return target.invokeExact(a0, a1, filter.invokeExact()); } protected Object invoke_Y0(Object a0, Object a1) throws Throwable { Object[] av = { a0, a1 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1]); } } static class F3 extends Adapter { @@ -585,7 +585,7 @@ class genclasses { return target.invokeExact(a0, a1, a2, filter.invokeExact()); } protected Object invoke_Y0(Object a0, Object a1, Object a2) throws Throwable { Object[] av = { a0, a1, a2 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2]); } } static class F4 extends Adapter { @@ -629,7 +629,7 @@ class genclasses { return target.invokeExact(a0, a1, a2, a3, filter.invokeExact()); } protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3) throws Throwable { Object[] av = { a0, a1, a2, a3 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3]); } } static class F5 extends Adapter { @@ -698,7 +698,7 @@ class genclasses { protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { Object[] av = { a0, a1, a2, a3, a4 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4]); } } static class F6 extends Adapter { @@ -777,7 +777,7 @@ class genclasses { protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5]); } } static class F7 extends Adapter { @@ -866,7 +866,7 @@ class genclasses { protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6]); } } static class F8 extends Adapter { @@ -965,7 +965,7 @@ class genclasses { protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7]); } } static class F9 extends Adapter { @@ -1104,7 +1104,7 @@ class genclasses { Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8]); } } static class F10 extends Adapter { @@ -1256,7 +1256,7 @@ class genclasses { Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9]); } } static class F11 extends Adapter { @@ -1442,7 +1442,7 @@ class genclasses { Object a4, Object a5, Object a6, Object a7, Object a8, Object a9, Object a10) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10]); } } static class F12 extends Adapter { @@ -1644,7 +1644,7 @@ class genclasses { Object a4, Object a5, Object a6, Object a7, Object a8, Object a9, Object a10, Object a11) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11]); } } static class F13 extends Adapter { @@ -1904,7 +1904,7 @@ class genclasses { Object a8, Object a9, Object a10, Object a11, Object a12) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12]); } } static class F14 extends Adapter { @@ -2183,7 +2183,7 @@ class genclasses { Object a8, Object a9, Object a10, Object a11, Object a12, Object a13) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13]); } } static class F15 extends Adapter { @@ -2481,7 +2481,7 @@ class genclasses { Object a8, Object a9, Object a10, Object a11, Object a12, Object a13, Object a14) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14]); } } static class F16 extends Adapter { @@ -2798,7 +2798,7 @@ class genclasses { Object a8, Object a9, Object a10, Object a11, Object a12, Object a13, Object a14, Object a15) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15]); } } static class F17 extends Adapter { @@ -3188,7 +3188,7 @@ class genclasses { Object a12, Object a13, Object a14, Object a15, Object a16) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16]); } } static class F18 extends Adapter { @@ -3600,7 +3600,7 @@ class genclasses { Object a12, Object a13, Object a14, Object a15, Object a16, Object a17) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17]); } } static class F19 extends Adapter { @@ -4034,7 +4034,7 @@ class genclasses { Object a12, Object a13, Object a14, Object a15, Object a16, Object a17, Object a18) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18]); } } static class F20 extends Adapter { @@ -4490,7 +4490,7 @@ class genclasses { Object a12, Object a13, Object a14, Object a15, Object a16, Object a17, Object a18, Object a19) throws Throwable { Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19 }; - filter.invokeExact(av); // make the flyby + filter.invokeExact(av); // make the flyby return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18], av[19]); } } } diff --git a/jdk/src/share/classes/sun/dyn/FromGeneric.java b/jdk/src/share/classes/sun/dyn/FromGeneric.java index 3e0d215fc97..4651d449faa 100644 --- a/jdk/src/share/classes/sun/dyn/FromGeneric.java +++ b/jdk/src/share/classes/sun/dyn/FromGeneric.java @@ -283,11 +283,11 @@ class FromGeneric { // { return new ThisType(entryPoint, convert, target); } /// Conversions on the value returned from the target. - protected Object convert_L(Object result) throws Throwable { return convert.invokeExact(result); } - protected Object convert_I(int result) throws Throwable { return convert.invokeExact(result); } - protected Object convert_J(long result) throws Throwable { return convert.invokeExact(result); } - protected Object convert_F(float result) throws Throwable { return convert.invokeExact(result); } - protected Object convert_D(double result) throws Throwable { return convert.invokeExact(result); } + protected Object convert_L(Object result) throws Throwable { return convert.invokeExact(result); } + protected Object convert_I(int result) throws Throwable { return convert.invokeExact(result); } + protected Object convert_J(long result) throws Throwable { return convert.invokeExact(result); } + protected Object convert_F(float result) throws Throwable { return convert.invokeExact(result); } + protected Object convert_D(double result) throws Throwable { return convert.invokeExact(result); } static private final String CLASS_PREFIX; // "sun.dyn.FromGeneric$" static { @@ -316,11 +316,11 @@ class FromGeneric { { super(e, i, c, t); } protected xA2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new xA2(e, i, c, t); } - protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L(invoker.invokeExact(target, a0, a1)); } - protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I(invoker.invokeExact(target, a0, a1)); } - protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J(invoker.invokeExact(target, a0, a1)); } - protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F(invoker.invokeExact(target, a0, a1)); } - protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D(invoker.invokeExact(target, a0, a1)); } + protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); } + protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1)); } + protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1)); } + protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); } + protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); } } // */ @@ -329,7 +329,8 @@ class FromGeneric { //{{{ import java.util.*; class genclasses { - static String[] TYPES = { "Object", "int ", "long ", "float ", "double" }; + static String[] TYPES = { "Object", "int ", "long ", "float ", "double" }; + static String[] WRAPS = { " ", "(Integer)", "(Long) ", "(Float) ", "(Double) " }; static String[] TCHARS = { "L", "I", "J", "F", "D", "A" }; static String[][] TEMPLATES = { { "@for@ arity=0..10 rcat<=4 nrefs<=99 nints=0 nlongs=0", @@ -341,13 +342,13 @@ class genclasses { " protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)", " { return new @cat@(e, i, c, t); }", " //@each-R@", - " protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@(invoker.<@R@>invokeExact(target@av@)); }", + " protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@((@R@)@W@invoker.invokeExact(target@av@)); }", " //@end-R@", " }", } }; static final String NEWLINE_INDENT = "\n "; enum VAR { - cat, catN, R, Rc, av, Tvav, Ovav; + cat, catN, R, Rc, W, av, Tvav, Ovav; public final String pattern = "@"+toString().replace('_','.')+"@"; public String binding; static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) { @@ -357,6 +358,7 @@ class genclasses { VAR.catN.binding = catstr(rcat, nrefs, nints, nlongs); VAR.R.binding = TYPES[rcat]; VAR.Rc.binding = TCHARS[rcat]; + VAR.W.binding = WRAPS[rcat]; String[] Tv = new String[nargs]; String[] av = new String[nargs]; String[] Tvav = new String[nargs]; @@ -497,11 +499,11 @@ class genclasses { { super(e, i, c, t); } protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A0(e, i, c, t); } - protected Object invoke_L0() throws Throwable { return convert_L(invoker.invokeExact(target)); } - protected Object invoke_I0() throws Throwable { return convert_I(invoker.invokeExact(target)); } - protected Object invoke_J0() throws Throwable { return convert_J(invoker.invokeExact(target)); } - protected Object invoke_F0() throws Throwable { return convert_F(invoker.invokeExact(target)); } - protected Object invoke_D0() throws Throwable { return convert_D(invoker.invokeExact(target)); } + protected Object invoke_L0() throws Throwable { return convert_L((Object)invoker.invokeExact(target)); } + protected Object invoke_I0() throws Throwable { return convert_I((int) invoker.invokeExact(target)); } + protected Object invoke_J0() throws Throwable { return convert_J((long) invoker.invokeExact(target)); } + protected Object invoke_F0() throws Throwable { return convert_F((float) invoker.invokeExact(target)); } + protected Object invoke_D0() throws Throwable { return convert_D((double)invoker.invokeExact(target)); } } static class A1 extends Adapter { protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -509,11 +511,11 @@ class genclasses { { super(e, i, c, t); } protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); } - protected Object invoke_L1(Object a0) throws Throwable { return convert_L(invoker.invokeExact(target, a0)); } - protected Object invoke_I1(Object a0) throws Throwable { return convert_I(invoker.invokeExact(target, a0)); } - protected Object invoke_J1(Object a0) throws Throwable { return convert_J(invoker.invokeExact(target, a0)); } - protected Object invoke_F1(Object a0) throws Throwable { return convert_F(invoker.invokeExact(target, a0)); } - protected Object invoke_D1(Object a0) throws Throwable { return convert_D(invoker.invokeExact(target, a0)); } + protected Object invoke_L1(Object a0) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0)); } + protected Object invoke_I1(Object a0) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0)); } + protected Object invoke_J1(Object a0) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0)); } + protected Object invoke_F1(Object a0) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0)); } + protected Object invoke_D1(Object a0) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0)); } } static class A2 extends Adapter { protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -521,11 +523,11 @@ class genclasses { { super(e, i, c, t); } protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A2(e, i, c, t); } - protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L(invoker.invokeExact(target, a0, a1)); } - protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I(invoker.invokeExact(target, a0, a1)); } - protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J(invoker.invokeExact(target, a0, a1)); } - protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F(invoker.invokeExact(target, a0, a1)); } - protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D(invoker.invokeExact(target, a0, a1)); } + protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); } + protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1)); } + protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1)); } + protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); } + protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); } } static class A3 extends Adapter { protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -533,11 +535,11 @@ class genclasses { { super(e, i, c, t); } protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A3(e, i, c, t); } - protected Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L(invoker.invokeExact(target, a0, a1, a2)); } - protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I(invoker.invokeExact(target, a0, a1, a2)); } - protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J(invoker.invokeExact(target, a0, a1, a2)); } - protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F(invoker.invokeExact(target, a0, a1, a2)); } - protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D(invoker.invokeExact(target, a0, a1, a2)); } + protected Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2)); } + protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2)); } + protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2)); } + protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2)); } + protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2)); } } static class A4 extends Adapter { protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -545,11 +547,11 @@ class genclasses { { super(e, i, c, t); } protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A4(e, i, c, t); } - protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L(invoker.invokeExact(target, a0, a1, a2, a3)); } - protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I(invoker.invokeExact(target, a0, a1, a2, a3)); } - protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J(invoker.invokeExact(target, a0, a1, a2, a3)); } - protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F(invoker.invokeExact(target, a0, a1, a2, a3)); } - protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D(invoker.invokeExact(target, a0, a1, a2, a3)); } + protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3)); } + protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3)); } + protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3)); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3)); } + protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3)); } } static class A5 extends Adapter { protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -557,11 +559,11 @@ class genclasses { { super(e, i, c, t); } protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A5(e, i, c, t); } - protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L(invoker.invokeExact(target, a0, a1, a2, a3, a4)); } - protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_I(invoker.invokeExact(target, a0, a1, a2, a3, a4)); } - protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_J(invoker.invokeExact(target, a0, a1, a2, a3, a4)); } - protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_F(invoker.invokeExact(target, a0, a1, a2, a3, a4)); } - protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_D(invoker.invokeExact(target, a0, a1, a2, a3, a4)); } + protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4)); } + protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4)); } + protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4)); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4)); } + protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4)); } } static class A6 extends Adapter { protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -569,11 +571,11 @@ class genclasses { { super(e, i, c, t); } protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A6(e, i, c, t); } - protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); } - protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_I(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); } - protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_J(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); } - protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_F(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); } - protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_D(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); } + protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); } + protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); } + protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); } + protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); } } static class A7 extends Adapter { protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -581,11 +583,11 @@ class genclasses { { super(e, i, c, t); } protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A7(e, i, c, t); } - protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_I(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_J(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_F(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_D(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); } } static class A8 extends Adapter { protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -593,11 +595,11 @@ class genclasses { { super(e, i, c, t); } protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A8(e, i, c, t); } - protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_I(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_J(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_F(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_D(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); } } static class A9 extends Adapter { protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -605,11 +607,11 @@ class genclasses { { super(e, i, c, t); } protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A9(e, i, c, t); } - protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_L(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_I(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_J(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_F(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_D(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } } static class A10 extends Adapter { protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -617,10 +619,10 @@ class genclasses { { super(e, i, c, t); } protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A10(e, i, c, t); } - protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_L(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_I(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_J(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_F(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_D(invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } } } diff --git a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java index 85b9f01f55d..24f7aae73a9 100644 --- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java +++ b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java @@ -245,52 +245,52 @@ public abstract class MethodHandleImpl { } private C invoke_V(Object... av) throws Throwable { C obj = allocate(); - rawConstructor.invokeExact((Object)obj, av); + rawConstructor.invokeExact((Object)obj, av); return obj; } private C invoke_L0() throws Throwable { C obj = allocate(); - rawConstructor.invokeExact((Object)obj); + rawConstructor.invokeExact((Object)obj); return obj; } private C invoke_L1(Object a0) throws Throwable { C obj = allocate(); - rawConstructor.invokeExact((Object)obj, a0); + rawConstructor.invokeExact((Object)obj, a0); return obj; } private C invoke_L2(Object a0, Object a1) throws Throwable { C obj = allocate(); - rawConstructor.invokeExact((Object)obj, a0, a1); + rawConstructor.invokeExact((Object)obj, a0, a1); return obj; } private C invoke_L3(Object a0, Object a1, Object a2) throws Throwable { C obj = allocate(); - rawConstructor.invokeExact((Object)obj, a0, a1, a2); + rawConstructor.invokeExact((Object)obj, a0, a1, a2); return obj; } private C invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { C obj = allocate(); - rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3); + rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3); return obj; } private C invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { C obj = allocate(); - rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4); + rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4); return obj; } private C invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { C obj = allocate(); - rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5); + rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5); return obj; } private C invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { C obj = allocate(); - rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6); + rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6); return obj; } private C invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { C obj = allocate(); - rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7); + rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7); return obj; } static MethodHandle[] makeInvokes() { @@ -951,54 +951,54 @@ public abstract class MethodHandleImpl { return addTypeString(target, this); } private Object invoke_V(Object... av) throws Throwable { - if (test.invokeExact(av)) - return target.invokeExact(av); - return fallback.invokeExact(av); + if ((boolean) test.invokeExact(av)) + return target.invokeExact(av); + return fallback.invokeExact(av); } private Object invoke_L0() throws Throwable { - if (test.invokeExact()) - return target.invokeExact(); - return fallback.invokeExact(); + if ((boolean) test.invokeExact()) + return target.invokeExact(); + return fallback.invokeExact(); } private Object invoke_L1(Object a0) throws Throwable { - if (test.invokeExact(a0)) - return target.invokeExact(a0); - return fallback.invokeExact(a0); + if ((boolean) test.invokeExact(a0)) + return target.invokeExact(a0); + return fallback.invokeExact(a0); } private Object invoke_L2(Object a0, Object a1) throws Throwable { - if (test.invokeExact(a0, a1)) - return target.invokeExact(a0, a1); - return fallback.invokeExact(a0, a1); + if ((boolean) test.invokeExact(a0, a1)) + return target.invokeExact(a0, a1); + return fallback.invokeExact(a0, a1); } private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { - if (test.invokeExact(a0, a1, a2)) - return target.invokeExact(a0, a1, a2); - return fallback.invokeExact(a0, a1, a2); + if ((boolean) test.invokeExact(a0, a1, a2)) + return target.invokeExact(a0, a1, a2); + return fallback.invokeExact(a0, a1, a2); } private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { - if (test.invokeExact(a0, a1, a2, a3)) - return target.invokeExact(a0, a1, a2, a3); - return fallback.invokeExact(a0, a1, a2, a3); + if ((boolean) test.invokeExact(a0, a1, a2, a3)) + return target.invokeExact(a0, a1, a2, a3); + return fallback.invokeExact(a0, a1, a2, a3); } private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { - if (test.invokeExact(a0, a1, a2, a3, a4)) - return target.invokeExact(a0, a1, a2, a3, a4); - return fallback.invokeExact(a0, a1, a2, a3, a4); + if ((boolean) test.invokeExact(a0, a1, a2, a3, a4)) + return target.invokeExact(a0, a1, a2, a3, a4); + return fallback.invokeExact(a0, a1, a2, a3, a4); } private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { - if (test.invokeExact(a0, a1, a2, a3, a4, a5)) - return target.invokeExact(a0, a1, a2, a3, a4, a5); - return fallback.invokeExact(a0, a1, a2, a3, a4, a5); + if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5)) + return target.invokeExact(a0, a1, a2, a3, a4, a5); + return fallback.invokeExact(a0, a1, a2, a3, a4, a5); } private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { - if (test.invokeExact(a0, a1, a2, a3, a4, a5, a6)) - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); - return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6); + if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6)) + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); + return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6); } private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { - if (test.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7)) - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); - return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); + if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7)) + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); + return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); } static MethodHandle[] makeInvokes() { ArrayList invokes = new ArrayList(); @@ -1058,82 +1058,82 @@ public abstract class MethodHandleImpl { } private Object invoke_V(Object... av) throws Throwable { try { - return target.invokeExact(av); + return target.invokeExact(av); } catch (Throwable t) { if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, av); + return catcher.invokeExact(t, av); } } private Object invoke_L0() throws Throwable { try { - return target.invokeExact(); + return target.invokeExact(); } catch (Throwable t) { if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t); + return catcher.invokeExact(t); } } private Object invoke_L1(Object a0) throws Throwable { try { - return target.invokeExact(a0); + return target.invokeExact(a0); } catch (Throwable t) { if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0); + return catcher.invokeExact(t, a0); } } private Object invoke_L2(Object a0, Object a1) throws Throwable { try { - return target.invokeExact(a0, a1); + return target.invokeExact(a0, a1); } catch (Throwable t) { if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1); + return catcher.invokeExact(t, a0, a1); } } private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { try { - return target.invokeExact(a0, a1, a2); + return target.invokeExact(a0, a1, a2); } catch (Throwable t) { if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2); + return catcher.invokeExact(t, a0, a1, a2); } } private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { try { - return target.invokeExact(a0, a1, a2, a3); + return target.invokeExact(a0, a1, a2, a3); } catch (Throwable t) { if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3); + return catcher.invokeExact(t, a0, a1, a2, a3); } } private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { try { - return target.invokeExact(a0, a1, a2, a3, a4); + return target.invokeExact(a0, a1, a2, a3, a4); } catch (Throwable t) { if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4); + return catcher.invokeExact(t, a0, a1, a2, a3, a4); } } private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { try { - return target.invokeExact(a0, a1, a2, a3, a4, a5); + return target.invokeExact(a0, a1, a2, a3, a4, a5); } catch (Throwable t) { if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5); + return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5); } } private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { try { - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); } catch (Throwable t) { if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6); + return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6); } } private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { try { - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); } catch (Throwable t) { if (!exType.isInstance(t)) throw t; - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7); + return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7); } } static MethodHandle[] makeInvokes() { diff --git a/jdk/src/share/classes/sun/dyn/SpreadGeneric.java b/jdk/src/share/classes/sun/dyn/SpreadGeneric.java index 5ba601b13d7..d95f3b963d4 100644 --- a/jdk/src/share/classes/sun/dyn/SpreadGeneric.java +++ b/jdk/src/share/classes/sun/dyn/SpreadGeneric.java @@ -277,12 +277,12 @@ class SpreadGeneric { protected xS2(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected xS2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new xS2(outer, t); } protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av,0); - return target.invokeExact(a0, a1)); } + return target.invokeExact(a0, a1)); } protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av,1); - return target.invokeExact(a0, + return target.invokeExact(a0, super.select(av,0)); } protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av,1); - return target.invokeExact( + return target.invokeExact( super.select(av,0), super.select(av,1)); } } // */ @@ -300,10 +300,10 @@ class genclasses { " protected @cat@(SpreadGeneric outer, MethodHandle t) { super(outer, t); }", " protected @cat@ makeInstance(SpreadGeneric outer, MethodHandle t) { return new @cat@(outer, t); }", " protected Object invoke_S0(@Tvav,@Object av) throws Throwable { av = super.check(av, 0);", - " return target.invokeExact(@av@); }", + " return target.invokeExact(@av@); }", " //@each-S@", " protected Object invoke_S@S@(@Tvav,@Object av) throws Throwable { av = super.check(av, @S@);", - " return target.invokeExact(@av,@@sv@); }", + " return target.invokeExact(@av,@@sv@); }", " //@end-S@", " }", } }; @@ -414,16 +414,16 @@ class genclasses { protected S0(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected S0 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S0(outer, t); } protected Object invoke_S0(Object av) throws Throwable { av = super.check(av, 0); - return target.invokeExact(); } + return target.invokeExact(); } } static class S1 extends Adapter { protected S1(SpreadGeneric outer) { super(outer); } // to build prototype protected S1(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected S1 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S1(outer, t); } protected Object invoke_S0(Object a0, Object av) throws Throwable { av = super.check(av, 0); - return target.invokeExact(a0); } + return target.invokeExact(a0); } protected Object invoke_S1(Object av) throws Throwable { av = super.check(av, 1); - return target.invokeExact( + return target.invokeExact( super.select(av,0)); } } static class S2 extends Adapter { @@ -431,12 +431,12 @@ class genclasses { protected S2(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected S2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S2(outer, t); } protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 0); - return target.invokeExact(a0, a1); } + return target.invokeExact(a0, a1); } protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av, 1); - return target.invokeExact(a0, + return target.invokeExact(a0, super.select(av,0)); } protected Object invoke_S2(Object av) throws Throwable { av = super.check(av, 2); - return target.invokeExact( + return target.invokeExact( super.select(av,0), super.select(av,1)); } } static class S3 extends Adapter { @@ -444,15 +444,15 @@ class genclasses { protected S3(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected S3 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S3(outer, t); } protected Object invoke_S0(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 0); - return target.invokeExact(a0, a1, a2); } + return target.invokeExact(a0, a1, a2); } protected Object invoke_S1(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 1); - return target.invokeExact(a0, a1, + return target.invokeExact(a0, a1, super.select(av,0)); } protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av, 2); - return target.invokeExact(a0, + return target.invokeExact(a0, super.select(av,0), super.select(av,1)); } protected Object invoke_S3(Object av) throws Throwable { av = super.check(av, 3); - return target.invokeExact( + return target.invokeExact( super.select(av,0), super.select(av,1), super.select(av,2)); } } static class S4 extends Adapter { @@ -460,18 +460,18 @@ class genclasses { protected S4(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected S4 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S4(outer, t); } protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 0); - return target.invokeExact(a0, a1, a2, a3); } + return target.invokeExact(a0, a1, a2, a3); } protected Object invoke_S1(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 1); - return target.invokeExact(a0, a1, a2, + return target.invokeExact(a0, a1, a2, super.select(av,0)); } protected Object invoke_S2(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 2); - return target.invokeExact(a0, a1, + return target.invokeExact(a0, a1, super.select(av,0), super.select(av,1)); } protected Object invoke_S3(Object a0, Object av) throws Throwable { av = super.check(av, 3); - return target.invokeExact(a0, + return target.invokeExact(a0, super.select(av,0), super.select(av,1), super.select(av,2)); } protected Object invoke_S4(Object av) throws Throwable { av = super.check(av, 4); - return target.invokeExact( + return target.invokeExact( super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } } static class S5 extends Adapter { @@ -479,21 +479,21 @@ class genclasses { protected S5(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected S5 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S5(outer, t); } protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 0); - return target.invokeExact(a0, a1, a2, a3, a4); } + return target.invokeExact(a0, a1, a2, a3, a4); } protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 1); - return target.invokeExact(a0, a1, a2, a3, + return target.invokeExact(a0, a1, a2, a3, super.select(av,0)); } protected Object invoke_S2(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 2); - return target.invokeExact(a0, a1, a2, + return target.invokeExact(a0, a1, a2, super.select(av,0), super.select(av,1)); } protected Object invoke_S3(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 3); - return target.invokeExact(a0, a1, + return target.invokeExact(a0, a1, super.select(av,0), super.select(av,1), super.select(av,2)); } protected Object invoke_S4(Object a0, Object av) throws Throwable { av = super.check(av, 4); - return target.invokeExact(a0, + return target.invokeExact(a0, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } protected Object invoke_S5(Object av) throws Throwable { av = super.check(av, 5); - return target.invokeExact( + return target.invokeExact( super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4)); } } @@ -502,25 +502,25 @@ class genclasses { protected S6(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected S6 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S6(outer, t); } protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 0); - return target.invokeExact(a0, a1, a2, a3, a4, a5); } + return target.invokeExact(a0, a1, a2, a3, a4, a5); } protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 1); - return target.invokeExact(a0, a1, a2, a3, a4, + return target.invokeExact(a0, a1, a2, a3, a4, super.select(av,0)); } protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 2); - return target.invokeExact(a0, a1, a2, a3, + return target.invokeExact(a0, a1, a2, a3, super.select(av,0), super.select(av,1)); } protected Object invoke_S3(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 3); - return target.invokeExact(a0, a1, a2, + return target.invokeExact(a0, a1, a2, super.select(av,0), super.select(av,1), super.select(av,2)); } protected Object invoke_S4(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 4); - return target.invokeExact(a0, a1, + return target.invokeExact(a0, a1, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } protected Object invoke_S5(Object a0, Object av) throws Throwable { av = super.check(av, 5); - return target.invokeExact(a0, + return target.invokeExact(a0, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4)); } protected Object invoke_S6(Object av) throws Throwable { av = super.check(av, 6); - return target.invokeExact( + return target.invokeExact( super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5)); } } @@ -529,29 +529,29 @@ class genclasses { protected S7(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected S7 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S7(outer, t); } protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 0); - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); } + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); } protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 1); - return target.invokeExact(a0, a1, a2, a3, a4, a5, + return target.invokeExact(a0, a1, a2, a3, a4, a5, super.select(av,0)); } protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 2); - return target.invokeExact(a0, a1, a2, a3, a4, + return target.invokeExact(a0, a1, a2, a3, a4, super.select(av,0), super.select(av,1)); } protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 3); - return target.invokeExact(a0, a1, a2, a3, + return target.invokeExact(a0, a1, a2, a3, super.select(av,0), super.select(av,1), super.select(av,2)); } protected Object invoke_S4(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 4); - return target.invokeExact(a0, a1, a2, + return target.invokeExact(a0, a1, a2, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } protected Object invoke_S5(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 5); - return target.invokeExact(a0, a1, + return target.invokeExact(a0, a1, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4)); } protected Object invoke_S6(Object a0, Object av) throws Throwable { av = super.check(av, 6); - return target.invokeExact(a0, + return target.invokeExact(a0, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5)); } protected Object invoke_S7(Object av) throws Throwable { av = super.check(av, 7); - return target.invokeExact( + return target.invokeExact( super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5), super.select(av,6)); } } @@ -560,33 +560,33 @@ class genclasses { protected S8(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected S8 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S8(outer, t); } protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 0); - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); } + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 1); - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, super.select(av,0)); } protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 2); - return target.invokeExact(a0, a1, a2, a3, a4, a5, + return target.invokeExact(a0, a1, a2, a3, a4, a5, super.select(av,0), super.select(av,1)); } protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 3); - return target.invokeExact(a0, a1, a2, a3, a4, + return target.invokeExact(a0, a1, a2, a3, a4, super.select(av,0), super.select(av,1), super.select(av,2)); } protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 4); - return target.invokeExact(a0, a1, a2, a3, + return target.invokeExact(a0, a1, a2, a3, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } protected Object invoke_S5(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 5); - return target.invokeExact(a0, a1, a2, + return target.invokeExact(a0, a1, a2, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4)); } protected Object invoke_S6(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 6); - return target.invokeExact(a0, a1, + return target.invokeExact(a0, a1, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5)); } protected Object invoke_S7(Object a0, Object av) throws Throwable { av = super.check(av, 7); - return target.invokeExact(a0, + return target.invokeExact(a0, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5), super.select(av,6)); } protected Object invoke_S8(Object av) throws Throwable { av = super.check(av, 8); - return target.invokeExact( + return target.invokeExact( super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); } } @@ -595,37 +595,37 @@ class genclasses { protected S9(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected S9 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S9(outer, t); } protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 0); - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 1); - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, super.select(av,0)); } protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 2); - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, super.select(av,0), super.select(av,1)); } protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 3); - return target.invokeExact(a0, a1, a2, a3, a4, a5, + return target.invokeExact(a0, a1, a2, a3, a4, a5, super.select(av,0), super.select(av,1), super.select(av,2)); } protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 4); - return target.invokeExact(a0, a1, a2, a3, a4, + return target.invokeExact(a0, a1, a2, a3, a4, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 5); - return target.invokeExact(a0, a1, a2, a3, + return target.invokeExact(a0, a1, a2, a3, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4)); } protected Object invoke_S6(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 6); - return target.invokeExact(a0, a1, a2, + return target.invokeExact(a0, a1, a2, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5)); } protected Object invoke_S7(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 7); - return target.invokeExact(a0, a1, + return target.invokeExact(a0, a1, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5), super.select(av,6)); } protected Object invoke_S8(Object a0, Object av) throws Throwable { av = super.check(av, 8); - return target.invokeExact(a0, + return target.invokeExact(a0, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); } protected Object invoke_S9(Object av) throws Throwable { av = super.check(av, 9); - return target.invokeExact( + return target.invokeExact( super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7), super.select(av,8)); } @@ -635,42 +635,42 @@ class genclasses { protected S10(SpreadGeneric outer, MethodHandle t) { super(outer, t); } protected S10 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S10(outer, t); } protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9, Object av) throws Throwable { av = super.check(av, 0); - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 1); - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, super.select(av,0)); } protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 2); - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, super.select(av,0), super.select(av,1)); } protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 3); - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, + return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, super.select(av,0), super.select(av,1), super.select(av,2)); } protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 4); - return target.invokeExact(a0, a1, a2, a3, a4, a5, + return target.invokeExact(a0, a1, a2, a3, a4, a5, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 5); - return target.invokeExact(a0, a1, a2, a3, a4, + return target.invokeExact(a0, a1, a2, a3, a4, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4)); } protected Object invoke_S6(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 6); - return target.invokeExact(a0, a1, a2, a3, + return target.invokeExact(a0, a1, a2, a3, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5)); } protected Object invoke_S7(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 7); - return target.invokeExact(a0, a1, a2, + return target.invokeExact(a0, a1, a2, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5), super.select(av,6)); } protected Object invoke_S8(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 8); - return target.invokeExact(a0, a1, + return target.invokeExact(a0, a1, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); } protected Object invoke_S9(Object a0, Object av) throws Throwable { av = super.check(av, 9); - return target.invokeExact(a0, + return target.invokeExact(a0, super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7), super.select(av,8)); } protected Object invoke_S10(Object av) throws Throwable { av = super.check(av, 10); - return target.invokeExact( + return target.invokeExact( super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7), super.select(av,8), super.select(av,9)); } diff --git a/jdk/src/share/classes/sun/dyn/ToGeneric.java b/jdk/src/share/classes/sun/dyn/ToGeneric.java index 80e7430dbe6..c6396454e87 100644 --- a/jdk/src/share/classes/sun/dyn/ToGeneric.java +++ b/jdk/src/share/classes/sun/dyn/ToGeneric.java @@ -367,33 +367,33 @@ class ToGeneric { // { return new ThisType(entryPoint, convert, target); } // Code to run when the arguments (<= 4) have all been boxed. - protected Object target() throws Throwable { return invoker.invokeExact(target); } - protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); } + protected Object target() throws Throwable { return invoker.invokeExact(target); } + protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); } protected Object target(Object a0, Object a1) - throws Throwable { return invoker.invokeExact(target, a0, a1); } + throws Throwable { return invoker.invokeExact(target, a0, a1); } protected Object target(Object a0, Object a1, Object a2) - throws Throwable { return invoker.invokeExact(target, a0, a1, a2); } + throws Throwable { return invoker.invokeExact(target, a0, a1, a2); } protected Object target(Object a0, Object a1, Object a2, Object a3) - throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); } + throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); } /* - protected Object target_0(Object... av) throws Throwable { return invoker.invokeExact(target, av); } + protected Object target_0(Object... av) throws Throwable { return invoker.invokeExact(target, av); } protected Object target_1(Object a0, Object... av) - throws Throwable { return invoker.invokeExact(target, a0, (Object)av); } + throws Throwable { return invoker.invokeExact(target, a0, (Object)av); } protected Object target_2(Object a0, Object a1, Object... av) - throws Throwable { return invoker.invokeExact(target, a0, a1, (Object)av); } + throws Throwable { return invoker.invokeExact(target, a0, a1, (Object)av); } protected Object target_3(Object a0, Object a1, Object a2, Object... av) - throws Throwable { return invoker.invokeExact(target, a0, a1, a2, (Object)av); } + throws Throwable { return invoker.invokeExact(target, a0, a1, a2, (Object)av); } protected Object target_4(Object a0, Object a1, Object a2, Object a3, Object... av) - throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, (Object)av); } + throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, (Object)av); } // */ // (For more than 4 arguments, generate the code in the adapter itself.) // Code to run when the generic target has finished and produced a value. - protected Object return_L(Object res) throws Throwable { return convert.invokeExact(res); } - protected int return_I(Object res) throws Throwable { return convert.invokeExact(res); } - protected long return_J(Object res) throws Throwable { return convert.invokeExact(res); } - protected float return_F(Object res) throws Throwable { return convert.invokeExact(res); } - protected double return_D(Object res) throws Throwable { return convert.invokeExact(res); } + protected Object return_L(Object res) throws Throwable { return (Object)convert.invokeExact(res); } + protected int return_I(Object res) throws Throwable { return (int) convert.invokeExact(res); } + protected long return_J(Object res) throws Throwable { return (long) convert.invokeExact(res); } + protected float return_F(Object res) throws Throwable { return (float) convert.invokeExact(res); } + protected double return_D(Object res) throws Throwable { return (double)convert.invokeExact(res); } static private final String CLASS_PREFIX; // "sun.dyn.ToGeneric$" static { @@ -420,7 +420,7 @@ class ToGeneric { protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); } - protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); } + protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); } protected Object targetA1(Object a0) throws Throwable { return target(a0); } protected Object targetA1(int a0) throws Throwable { return target(a0); } protected Object targetA1(long a0) throws Throwable { return target(a0); } @@ -458,7 +458,7 @@ class genclasses { " protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype", " protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }", " protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }", - " protected Object target(@Ovav@) throws Throwable { return invoker.invokeExact(target, @av@); }", + " protected Object target(@Ovav@) throws Throwable { return invoker.invokeExact(target, @av@); }", " //@each-Tv@", " protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }", " //@end-Tv@", @@ -618,7 +618,7 @@ class genclasses { protected A0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A0(e, i, c, t); } - protected Object target() throws Throwable { return invoker.invokeExact(target); } + protected Object target() throws Throwable { return invoker.invokeExact(target); } protected Object targetA0() throws Throwable { return target(); } protected Object invoke_L() throws Throwable { return return_L(targetA0()); } protected int invoke_I() throws Throwable { return return_I(targetA0()); } @@ -630,7 +630,7 @@ class genclasses { protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); } - protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); } + protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); } protected Object targetA1(Object a0) throws Throwable { return target(a0); } protected Object targetA1(int a0) throws Throwable { return target(a0); } protected Object targetA1(long a0) throws Throwable { return target(a0); } @@ -654,7 +654,7 @@ class genclasses { protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A2(e, i, c, t); } - protected Object target(Object a0, Object a1) throws Throwable { return invoker.invokeExact(target, a0, a1); } + protected Object target(Object a0, Object a1) throws Throwable { return invoker.invokeExact(target, a0, a1); } protected Object targetA2(Object a0, Object a1) throws Throwable { return target(a0, a1); } protected Object targetA2(Object a0, int a1) throws Throwable { return target(a0, a1); } protected Object targetA2(int a0, int a1) throws Throwable { return target(a0, a1); } @@ -690,7 +690,7 @@ class genclasses { protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A3(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2) throws Throwable { return invoker.invokeExact(target, a0, a1, a2); } + protected Object target(Object a0, Object a1, Object a2) throws Throwable { return invoker.invokeExact(target, a0, a1, a2); } protected Object targetA3(Object a0, Object a1, Object a2) throws Throwable { return target(a0, a1, a2); } protected Object targetA3(Object a0, Object a1, int a2) throws Throwable { return target(a0, a1, a2); } protected Object targetA3(Object a0, int a1, int a2) throws Throwable { return target(a0, a1, a2); } @@ -739,7 +739,7 @@ class genclasses { protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A4(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); } + protected Object target(Object a0, Object a1, Object a2, Object a3) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); } protected Object targetA4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return target(a0, a1, a2, a3); } protected Object targetA4(Object a0, Object a1, Object a2, int a3) throws Throwable { return target(a0, a1, a2, a3); } protected Object targetA4(Object a0, Object a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); } @@ -781,7 +781,7 @@ class genclasses { protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A5(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return target(a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); } @@ -832,7 +832,7 @@ class genclasses { protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A6(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5); } protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); } protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); } protected Object targetA6(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); } @@ -866,7 +866,7 @@ class genclasses { protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A7(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6); } protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); } protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); } protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); } @@ -904,7 +904,7 @@ class genclasses { protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A8(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } @@ -946,7 +946,7 @@ class genclasses { protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A9(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } @@ -992,7 +992,7 @@ class genclasses { protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A10(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } diff --git a/jdk/test/java/dyn/InvokeGenericTest.java b/jdk/test/java/dyn/InvokeGenericTest.java index 1b20d95ea61..12670668c7e 100644 --- a/jdk/test/java/dyn/InvokeGenericTest.java +++ b/jdk/test/java/dyn/InvokeGenericTest.java @@ -25,7 +25,7 @@ /* @test * @summary unit tests for java.dyn.MethodHandle.invokeGeneric - * @compile -target 7 InvokeGenericTest.java + * @compile -XDallowTransitionalJSR292=no -target 7 InvokeGenericTest.java * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.InvokeGenericTest */ @@ -350,7 +350,7 @@ public class InvokeGenericTest { String[] args = { "one", "two" }; MethodHandle mh = callable(Object.class, String.class); Object res; List resl; - res = resl = (List) mh.invokeGeneric((String)args[0], (Object)args[1]); + res = resl = (List) mh.invokeGeneric((String)args[0], (Object)args[1]); //System.out.println(res); assertEquals(Arrays.asList(args), res); } @@ -476,7 +476,7 @@ public class InvokeGenericTest { Integer[] args = { 1, 2 }; MethodHandle mh = callable(Object.class, int.class); Object res; List resl; - res = resl = (List) mh.invokeGeneric((int)args[0], (Object)args[1]); + res = resl = (List) mh.invokeGeneric((int)args[0], (Object)args[1]); //System.out.println(res); assertEquals(Arrays.asList(args), res); } diff --git a/jdk/test/java/dyn/JavaDocExamplesTest.java b/jdk/test/java/dyn/JavaDocExamplesTest.java index 90290c60da6..1e29956e5fb 100644 --- a/jdk/test/java/dyn/JavaDocExamplesTest.java +++ b/jdk/test/java/dyn/JavaDocExamplesTest.java @@ -95,11 +95,11 @@ MethodHandle CONCAT_3 = LOOKUP.findVirtual(String.class, MethodHandle HASHCODE_3 = LOOKUP.findVirtual(Object.class, "hashCode", methodType(int.class)); //assertEquals("xy", (String) CONCAT_1.invokeExact("x", "y")); -assertEquals("xy", (String) CONCAT_2.invokeExact("x", "y")); -assertEquals("xy", (String) CONCAT_3.invokeExact("x", "y")); -//assertEquals("xy".hashCode(), (int) HASHCODE_1.invokeExact((Object)"xy")); -assertEquals("xy".hashCode(), (int) HASHCODE_2.invokeExact((Object)"xy")); -assertEquals("xy".hashCode(), (int) HASHCODE_3.invokeExact((Object)"xy")); +assertEquals("xy", (String) CONCAT_2.invokeExact("x", "y")); +assertEquals("xy", (String) CONCAT_3.invokeExact("x", "y")); +//assertEquals("xy".hashCode(), (int) HASHCODE_1.invokeExact((Object)"xy")); +assertEquals("xy".hashCode(), (int) HASHCODE_2.invokeExact((Object)"xy")); +assertEquals("xy".hashCode(), (int) HASHCODE_3.invokeExact((Object)"xy")); {} } @Test public void testDropArguments() throws Throwable { diff --git a/jdk/test/java/dyn/MethodHandlesTest.java b/jdk/test/java/dyn/MethodHandlesTest.java index 6a80775bf3d..f2ab7d36e5f 100644 --- a/jdk/test/java/dyn/MethodHandlesTest.java +++ b/jdk/test/java/dyn/MethodHandlesTest.java @@ -25,8 +25,8 @@ /* @test * @summary unit tests for java.dyn.MethodHandles - * @compile -XDinvokedynamic MethodHandlesTest.java - * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic test.java.dyn.MethodHandlesTest + * @compile -source 7 -target 7 -XDallowTransitionalJSR292=no MethodHandlesTest.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.MethodHandlesTest */ package test.java.dyn; @@ -891,12 +891,12 @@ public class MethodHandlesTest { for (int i = 0; i <= 1; i++) { if (isStatic) { if (type == int.class) - sawValue = mh.invokeExact(); // do these exactly + sawValue = (int) mh.invokeExact(); // do these exactly else sawValue = mh.invokeExact(); } else { if (type == int.class) - sawValue = mh.invokeExact((Object) fields); + sawValue = (int) mh.invokeExact((Object) fields); else sawValue = mh.invokeExact((Object) fields); } @@ -965,14 +965,14 @@ public class MethodHandlesTest { Object putValue = randomArg(type); if (isStatic) { if (type == int.class) - mh.invokeExact((int)(Integer)putValue); // do these exactly + mh.invokeExact((int)putValue); // do these exactly else - mh.invokeExact(putValue); + mh.invokeExact(putValue); } else { if (type == int.class) - mh.invokeExact((Object) fields, (int)(Integer)putValue); + mh.invokeExact((Object) fields, (int)putValue); else - mh.invokeExact((Object) fields, putValue); + mh.invokeExact((Object) fields, putValue); } assertEquals(f.get(fields), putValue); } @@ -1038,11 +1038,11 @@ public class MethodHandlesTest { model.set(i, random); if (testSetter) { if (elemType == int.class) - mh.invokeExact((int[]) array, i, (int)(Integer)random); + mh.invokeExact((int[]) array, i, (int)random); else if (elemType == boolean.class) - mh.invokeExact((boolean[]) array, i, (boolean)(Boolean)random); + mh.invokeExact((boolean[]) array, i, (boolean)random); else - mh.invokeExact(array, i, random); + mh.invokeExact(array, i, random); assertEquals(model, array2list(array)); } else { Array.set(array, i, random); @@ -1058,9 +1058,9 @@ public class MethodHandlesTest { if (!testSetter) { expValue = sawValue; if (elemType == int.class) - sawValue = mh.invokeExact((int[]) array, i); + sawValue = (int) mh.invokeExact((int[]) array, i); else if (elemType == boolean.class) - sawValue = mh.invokeExact((boolean[]) array, i); + sawValue = (boolean) mh.invokeExact((boolean[]) array, i); else sawValue = mh.invokeExact(array, i); assertEquals(sawValue, expValue); @@ -1355,15 +1355,15 @@ public class MethodHandlesTest { assertArrayEquals(args, check); switch (nargs) { case 0: - check = target.invokeExact(); + check = (Object[]) target.invokeExact(); assertArrayEquals(args, check); break; case 1: - check = target.invokeExact(args[0]); + check = (Object[]) target.invokeExact(args[0]); assertArrayEquals(args, check); break; case 2: - check = target.invokeExact(args[0], args[1]); + check = (Object[]) target.invokeExact(args[0], args[1]); assertArrayEquals(args, check); break; } @@ -1377,8 +1377,11 @@ public class MethodHandlesTest { MethodHandle result = MethodHandles.spreadArguments(target2, newType); Object[] returnValue; if (pos == 0) { - Object rawRetVal = result.invokeExact(args); - returnValue = (Object[]) rawRetVal; + // In the following line, the first cast implies + // normal Object return value for the MH call (Object[])->Object, + // while the second cast dynamically converts to an Object array. + // Such a double cast is typical of MH.invokeExact. + returnValue = (Object[]) (Object) result.invokeExact(args); } else { Object[] args1 = Arrays.copyOfRange(args, 0, pos+1); args1[pos] = Arrays.copyOfRange(args, pos, args.length); From 47d77755bcaa2c871822c76dc500ddf28abe9557 Mon Sep 17 00:00:00 2001 From: Vikram Aroskar Date: Mon, 29 Nov 2010 22:10:46 -0800 Subject: [PATCH 011/139] 6382377: incorrect Exception is given to interceptor 6828768: RMI-IIOP EJB clients do not fail over due to defect in JDK 1.6.0_12 Also reviewed by ken.cavanaugh@oracle.com Reviewed-by: skoppar --- .../encoding/BufferManagerWriteStream.java | 10 +++++++++- .../CorbaClientRequestDispatcherImpl.java | 20 +++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteStream.java b/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteStream.java index da369f9c365..0c7844325cd 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteStream.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteStream.java @@ -30,12 +30,14 @@ import com.sun.corba.se.impl.orbutil.ORBConstants; import com.sun.corba.se.impl.protocol.giopmsgheaders.Message; import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase; import com.sun.corba.se.impl.protocol.giopmsgheaders.FragmentMessage; +import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage; import com.sun.corba.se.impl.encoding.BufferManagerWrite; import com.sun.corba.se.impl.encoding.ByteBufferWithInfo; import com.sun.corba.se.impl.encoding.CDROutputObject; import com.sun.corba.se.spi.orb.ORB; import com.sun.corba.se.pept.transport.Connection; import com.sun.corba.se.pept.encoding.OutputObject; +import org.omg.CORBA.SystemException; /** * Streaming buffer manager. @@ -66,7 +68,13 @@ public class BufferManagerWriteStream extends BufferManagerWrite // Set the fragment's moreFragments field to true MessageBase.setFlag(bbwi.byteBuffer, Message.MORE_FRAGMENTS_BIT); - sendFragment(false); + try { + sendFragment(false); + } catch(SystemException se){ + orb.getPIHandler().invokeClientPIEndingPoint( + ReplyMessage.SYSTEM_EXCEPTION, se); + throw se; + } // Reuse the old buffer diff --git a/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java index d44873bd787..7728a677ecd 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java @@ -385,11 +385,15 @@ public class CorbaClientRequestDispatcherImpl boolean retry = getContactInfoListIterator(orb) .reportException(messageMediator.getContactInfo(), e); - if (retry) { - // Must run interceptor end point before retrying. - Exception newException = + + //Bug 6382377: must not lose exception in PI + + // Must run interceptor end point before retrying. + Exception newException = orb.getPIHandler().invokeClientPIEndingPoint( - ReplyMessage.SYSTEM_EXCEPTION, e); + ReplyMessage.SYSTEM_EXCEPTION, e); + + if (retry) { if (newException == e) { continueOrThrowSystemOrRemarshal(messageMediator, new RemarshalException()); @@ -398,6 +402,14 @@ public class CorbaClientRequestDispatcherImpl newException); } } else { + if (newException instanceof RuntimeException){ + throw (RuntimeException)newException; + } + else if (newException instanceof RemarshalException) + { + throw (RemarshalException)newException; + } + // NOTE: Interceptor ending point will run in releaseReply. throw e; } From 36b4f6058554d0557a6c73f9c0c0c161b41e5a66 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 30 Nov 2010 09:53:04 -0800 Subject: [PATCH 012/139] 7001363: java/dyn/InvokeDynamic should not be a well-known class in the JVM Because of the removal of language support, the JDK 7 API for JSR 292 no longer includes a public class named java/dyn/InvokeDynamic. Reviewed-by: jrose, kvn --- hotspot/src/share/vm/classfile/systemDictionary.cpp | 2 +- hotspot/src/share/vm/classfile/systemDictionary.hpp | 3 +-- hotspot/src/share/vm/prims/methodHandleWalk.cpp | 11 +++-------- hotspot/src/share/vm/prims/methodHandleWalk.hpp | 3 +-- hotspot/src/share/vm/prims/methodHandles.cpp | 5 ++--- hotspot/src/share/vm/runtime/thread.cpp | 6 ------ 6 files changed, 8 insertions(+), 22 deletions(-) diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index b6f8481a9f3..5716e87163e 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -2010,7 +2010,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { scan = WKID(meth_group_end+1); } WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass); - WKID indy_group_end = WK_KLASS_ENUM_NAME(InvokeDynamic_klass); + WKID indy_group_end = WK_KLASS_ENUM_NAME(CallSite_klass); initialize_wk_klasses_until(indy_group_start, scan, CHECK); if (EnableInvokeDynamic) { initialize_wk_klasses_through(indy_group_end, scan, CHECK); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index d18e341920d..a83c8d55120 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -156,8 +156,7 @@ class SymbolPropertyTable; template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \ template(Linkage_klass, java_dyn_Linkage, Opt) \ template(CallSite_klass, java_dyn_CallSite, Opt) \ - template(InvokeDynamic_klass, java_dyn_InvokeDynamic, Opt) \ - /* Note: MethodHandle must be first, and InvokeDynamic last in group */ \ + /* Note: MethodHandle must be first, and CallSite last in group */ \ \ template(StringBuffer_klass, java_lang_StringBuffer, Pre) \ template(StringBuilder_klass, java_lang_StringBuilder, Pre) \ diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.cpp b/hotspot/src/share/vm/prims/methodHandleWalk.cpp index 3965109f2a1..f20859dac8c 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp @@ -968,16 +968,11 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, if (tailcall) { // Actually, in order to make these methods more recognizable, - // let's put them in holder classes MethodHandle and InvokeDynamic. - // That way stack walkers and compiler heuristics can recognize them. - _target_klass = (for_invokedynamic() - ? SystemDictionary::InvokeDynamic_klass() - : SystemDictionary::MethodHandle_klass()); + // let's put them in holder class MethodHandle. That way stack + // walkers and compiler heuristics can recognize them. + _target_klass = SystemDictionary::MethodHandle_klass(); } - // instanceKlass* ik = instanceKlass::cast(klass); - // tty->print_cr("MethodHandleCompiler::make_invoke: %s %s.%s%s", Bytecodes::name(op), ik->external_name(), name->as_C_string(), signature->as_C_string()); - // Inline the method. InvocationCounter* ic = m->invocation_counter(); ic->set_carry_flag(); diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.hpp b/hotspot/src/share/vm/prims/methodHandleWalk.hpp index f4a6ad7b3da..91e71da33d8 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.hpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.hpp @@ -412,8 +412,7 @@ public: // Tests if the given class is a MH adapter holder. static bool klass_is_method_handle_adapter_holder(klassOop klass) { - return (klass == SystemDictionary::MethodHandle_klass() || - klass == SystemDictionary::InvokeDynamic_klass()); + return (klass == SystemDictionary::MethodHandle_klass()); } }; diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 67974a66534..6c33186561b 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -485,9 +485,8 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) { Handle polymorphic_method_type; bool polymorphic_signature = false; if ((flags & ALL_KINDS) == IS_METHOD && - (defc() == SystemDictionary::InvokeDynamic_klass() || - (defc() == SystemDictionary::MethodHandle_klass() && - methodOopDesc::is_method_handle_invoke_name(name())))) + (defc() == SystemDictionary::MethodHandle_klass() && + methodOopDesc::is_method_handle_invoke_name(name()))) polymorphic_signature = true; // convert the external string or reflective type to an internal signature diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 9447249ed0f..b7a224b93cf 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -3232,12 +3232,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { warning("java.lang.ArithmeticException has not been initialized"); warning("java.lang.StackOverflowError has not been initialized"); } - - if (EnableInvokeDynamic) { - // JSR 292: An intialized java.dyn.InvokeDynamic is required in - // the compiler. - initialize_class(vmSymbolHandles::java_dyn_InvokeDynamic(), CHECK_0); - } } // See : bugid 4211085. From 05ca2bb455f4a145ca0d3bf18ef84cb22c4f5dd0 Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Tue, 30 Nov 2010 17:46:42 -0800 Subject: [PATCH 013/139] 6987107: Add variable to add to but not modify non-fcs version string Reviewed-by: jcoomes, dholmes, andrew, kvn --- jdk/make/common/shared/Defs.gmk | 13 +++++++++---- jdk/make/jprt.gmk | 3 --- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/jdk/make/common/shared/Defs.gmk b/jdk/make/common/shared/Defs.gmk index ca55564560e..43e27a5a4ca 100644 --- a/jdk/make/common/shared/Defs.gmk +++ b/jdk/make/common/shared/Defs.gmk @@ -287,9 +287,12 @@ ifdef BUILD_NUMBER FULL_VERSION = $(RELEASE)-$(BUILD_NUMBER) else BUILD_NUMBER = b00 - BUILD_DATE := $(shell $(DATE) '+%Y_%m_%d_%H_%M') - CLEAN_USERNAME := $(shell $(ECHO) "$(USER)" | $(TR) -d -c '[:alnum:]') - USER_RELEASE_SUFFIX := $(shell $(ECHO) "$(CLEAN_USERNAME)_$(BUILD_DATE)" | $(TR) '[:upper:]' '[:lower:]' ) + ifndef USER_RELEASE_SUFFIX + BUILD_DATE := $(shell $(DATE) '+%Y_%m_%d_%H_%M') + CLEAN_USERNAME := $(shell $(ECHO) "$(USER)" | $(TR) -d -c '[:alnum:]') + USER_RELEASE_SUFFIX := $(shell $(ECHO) "$(CLEAN_USERNAME)_$(BUILD_DATE)" | $(TR) '[:upper:]' '[:lower:]' ) + endif + export USER_RELEASE_SUFFIX FULL_VERSION = $(RELEASE)-$(USER_RELEASE_SUFFIX)-$(BUILD_NUMBER) endif @@ -335,7 +338,9 @@ endif # Include any private definitions for this set of workspaces _PRIVATE_DEFS_FILE=$(JDK_MAKE_SHARED_DIR)/PrivateDefs.gmk -USING_PRIVATE_DEFS:=$(shell if [ -f $(_PRIVATE_DEFS_FILE) ]; then echo true; else echo false; fi) +ifeq ($(USING_PRIVATE_DEFS),) + USING_PRIVATE_DEFS:=$(shell if [ -f $(_PRIVATE_DEFS_FILE) ]; then echo true; else echo false; fi) +endif ifeq ($(USING_PRIVATE_DEFS),true) dummy:=$(warning "WARNING: Using definitions from $(_PRIVATE_DEFS_FILE)") include $(_PRIVATE_DEFS_FILE) diff --git a/jdk/make/jprt.gmk b/jdk/make/jprt.gmk index bd1189bf45e..3ad4c188243 100644 --- a/jdk/make/jprt.gmk +++ b/jdk/make/jprt.gmk @@ -26,9 +26,6 @@ # JPRT rule to build this workspace JPRT_ARCHIVE_BUNDLE=$(ABS_OUTPUTDIR)/$(JPRT_BUILD_FLAVOR)-bundle.zip -ifdef JPRT_BUILD_VERSION - MILESTONE=$(JPRT_BUILD_VERSION) -endif jprt_build_product: all images ( $(CD) $(OUTPUTDIR)/j2sdk-image && \ From 71f75cb4816f9f4fa8123b46005a364abb69ec7b Mon Sep 17 00:00:00 2001 From: Michael Fang Date: Tue, 30 Nov 2010 22:38:52 -0800 Subject: [PATCH 014/139] 6675400: "Details" in English has to be "Details" in German Reviewed-by: yhuang --- .../java/swing/plaf/windows/resources/windows_de.properties | 6 +++--- .../swing/internal/plaf/metal/resources/metal_de.properties | 6 +++--- .../swing/internal/plaf/synth/resources/synth_de.properties | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_de.properties b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_de.properties index 578f83c19f4..c08a39e5a1c 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_de.properties +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_de.properties @@ -33,11 +33,11 @@ FileChooser.newFolderActionLabelText=Neuer Ordner FileChooser.listViewButtonToolTipText=Liste FileChooser.listViewButtonAccessibleName=Liste FileChooser.listViewActionLabelText=Liste -FileChooser.detailsViewButtonToolTipText=Einzelheiten -FileChooser.detailsViewButtonAccessibleName=Einzelheiten +FileChooser.detailsViewButtonToolTipText=Details +FileChooser.detailsViewButtonAccessibleName=Details FileChooser.viewMenuButtonToolTipText = View Menu FileChooser.viewMenuButtonAccessibleName = View Menu -FileChooser.detailsViewActionLabelText=Einzelheiten +FileChooser.detailsViewActionLabelText=Details FileChooser.refreshActionLabelText=Aktualisieren FileChooser.viewMenuLabelText=Ansicht FileChooser.fileNameHeaderText=Dateiname diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties index 09c6a84ab57..1262ee30ff4 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties @@ -33,9 +33,9 @@ FileChooser.newFolderActionLabelText=Neuer Ordner FileChooser.listViewButtonToolTipText=Liste FileChooser.listViewButtonAccessibleName=Liste FileChooser.listViewActionLabelText=Liste -FileChooser.detailsViewButtonToolTipText=Einzelheiten -FileChooser.detailsViewButtonAccessibleName=Einzelheiten -FileChooser.detailsViewActionLabelText=Einzelheiten +FileChooser.detailsViewButtonToolTipText=Details +FileChooser.detailsViewButtonAccessibleName=Details +FileChooser.detailsViewActionLabelText=Details FileChooser.refreshActionLabelText=Aktualisieren FileChooser.viewMenuLabelText=Ansicht FileChooser.fileNameHeaderText=Dateiname diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_de.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_de.properties index 3bb5f63f2f6..67192ebc71d 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_de.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_de.properties @@ -28,8 +28,8 @@ FileChooser.newFolderToolTipText=Neuen Ordner erstellen FileChooser.newFolderAccessibleName=Neuer Ordner FileChooser.listViewButtonToolTipText=Liste FileChooser.listViewButtonAccessibleName=Liste -FileChooser.detailsViewButtonToolTipText=Einzelheiten -FileChooser.detailsViewButtonAccessibleName=Einzelheiten +FileChooser.detailsViewButtonToolTipText=Details +FileChooser.detailsViewButtonAccessibleName=Details FileChooser.fileNameHeaderText=Dateiname FileChooser.fileSizeHeaderText=Gr\u00f6\u00dfe FileChooser.fileTypeHeaderText=Typ From d59d7ffc4ab42869b9477be7bd805247794ccaba Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Tue, 30 Nov 2010 23:23:40 -0800 Subject: [PATCH 015/139] 6985015: C1 needs to support compressed oops This change implements compressed oops for C1 for x64 and sparc. The changes are mostly on the codegen level, with a few exceptions when we do access things outside of the heap that are uncompressed from the IR. Compressed oops are now also enabled with tiered. Reviewed-by: twisti, kvn, never, phh --- hotspot/src/cpu/sparc/vm/assembler_sparc.cpp | 4 +- hotspot/src/cpu/sparc/vm/assembler_sparc.hpp | 1 + .../src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp | 2 +- .../src/cpu/sparc/vm/c1_FrameMap_sparc.hpp | 3 + .../cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 438 ++++++++---------- .../cpu/sparc/vm/c1_LIRAssembler_sparc.hpp | 30 +- .../cpu/sparc/vm/c1_MacroAssembler_sparc.cpp | 20 +- .../src/cpu/sparc/vm/c1_Runtime1_sparc.cpp | 2 +- hotspot/src/cpu/x86/vm/assembler_x86.hpp | 1 + hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp | 2 +- hotspot/src/cpu/x86/vm/c1_Defs_x86.hpp | 4 +- hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp | 14 +- hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp | 11 + .../src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 188 +++++--- .../src/cpu/x86/vm/c1_LIRGenerator_x86.cpp | 14 +- hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp | 11 +- .../src/cpu/x86/vm/c1_MacroAssembler_x86.cpp | 29 +- hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp | 2 +- hotspot/src/share/vm/c1/c1_FrameMap.hpp | 8 +- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 2 +- hotspot/src/share/vm/c1/c1_Instruction.hpp | 11 +- hotspot/src/share/vm/c1/c1_LIR.cpp | 2 + hotspot/src/share/vm/c1/c1_LIR.hpp | 16 +- hotspot/src/share/vm/c1/c1_LIRAssembler.cpp | 12 +- hotspot/src/share/vm/c1/c1_LIRAssembler.hpp | 12 +- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 47 +- hotspot/src/share/vm/c1/c1_LinearScan.cpp | 6 +- hotspot/src/share/vm/c1/c1_Runtime1.cpp | 5 +- hotspot/src/share/vm/code/relocInfo.cpp | 4 +- hotspot/src/share/vm/runtime/arguments.cpp | 21 +- 30 files changed, 493 insertions(+), 429 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index 901931fb79f..cb7890e985d 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -909,10 +909,10 @@ void MacroAssembler::verify_thread() { #if defined(COMPILER2) && !defined(_LP64) // Save & restore possible 64-bit Long arguments in G-regs sllx(L0,32,G2); // Move old high G1 bits high in G2 - sllx(G1, 0,G1); // Clear current high G1 bits + srl(G1, 0,G1); // Clear current high G1 bits or3 (G1,G2,G1); // Recover 64-bit G1 sllx(L6,32,G2); // Move old high G4 bits high in G2 - sllx(G4, 0,G4); // Clear current high G4 bits + srl(G4, 0,G4); // Clear current high G4 bits or3 (G4,G2,G4); // Recover 64-bit G4 #endif restore(O0, 0, G2_thread); diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index f6ff1bde4e0..94a9dcaf667 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -1798,6 +1798,7 @@ class MacroAssembler: public Assembler { // branches that use right instruction for v8 vs. v9 inline void br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); inline void br( Condition c, bool a, Predict p, Label& L ); + inline void fb( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); inline void fb( Condition c, bool a, Predict p, Label& L ); diff --git a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp index f3149d7426e..ee5f6afb5de 100644 --- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp @@ -434,7 +434,7 @@ void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { Register pre_val_reg = pre_val()->as_register(); - ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false); + ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/); if (__ is_in_wdisp16_range(_continuation)) { __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, pre_val_reg, _continuation); diff --git a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp index 05e034096b4..2304c2d0103 100644 --- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp @@ -155,4 +155,7 @@ static bool is_caller_save_register (LIR_Opr reg); static bool is_caller_save_register (Register r); + static int nof_caller_save_cpu_regs() { return pd_nof_caller_save_cpu_regs_frame_map; } + static int last_cpu_reg() { return pd_last_cpu_reg; } + #endif // CPU_SPARC_VM_C1_FRAMEMAP_SPARC_HPP diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index b1e2a2b464f..d933aa00049 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -100,6 +100,11 @@ bool LIR_Assembler::is_single_instruction(LIR_Op* op) { return false; } + if (UseCompressedOops) { + if (dst->is_address() && !dst->is_stack() && (dst->type() == T_OBJECT || dst->type() == T_ARRAY)) return false; + if (src->is_address() && !src->is_stack() && (src->type() == T_OBJECT || src->type() == T_ARRAY)) return false; + } + if (dst->is_register()) { if (src->is_address() && Assembler::is_simm13(src->as_address_ptr()->disp())) { return !PatchALot; @@ -253,7 +258,7 @@ void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position int count_offset = java_lang_String:: count_offset_in_bytes(); - __ ld_ptr(str0, value_offset, tmp0); + __ load_heap_oop(str0, value_offset, tmp0); __ ld(str0, offset_offset, tmp2); __ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0); __ ld(str0, count_offset, str0); @@ -262,7 +267,7 @@ void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst // str1 may be null add_debug_info_for_null_check_here(info); - __ ld_ptr(str1, value_offset, tmp1); + __ load_heap_oop(str1, value_offset, tmp1); __ add(tmp0, tmp2, tmp0); __ ld(str1, offset_offset, tmp2); @@ -766,7 +771,7 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { add_debug_info_for_null_check_here(op->info()); - __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch); + __ load_klass(O0, G3_scratch); if (__ is_simm13(op->vtable_offset())) { __ ld_ptr(G3_scratch, op->vtable_offset(), G5_method); } else { @@ -780,138 +785,17 @@ void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { // the peephole pass fills the delay slot } - -// load with 32-bit displacement -int LIR_Assembler::load(Register s, int disp, Register d, BasicType ld_type, CodeEmitInfo *info) { - int load_offset = code_offset(); - if (Assembler::is_simm13(disp)) { - if (info != NULL) add_debug_info_for_null_check_here(info); - switch(ld_type) { - case T_BOOLEAN: // fall through - case T_BYTE : __ ldsb(s, disp, d); break; - case T_CHAR : __ lduh(s, disp, d); break; - case T_SHORT : __ ldsh(s, disp, d); break; - case T_INT : __ ld(s, disp, d); break; - case T_ADDRESS:// fall through - case T_ARRAY : // fall through - case T_OBJECT: __ ld_ptr(s, disp, d); break; - default : ShouldNotReachHere(); - } - } else { - __ set(disp, O7); - if (info != NULL) add_debug_info_for_null_check_here(info); - load_offset = code_offset(); - switch(ld_type) { - case T_BOOLEAN: // fall through - case T_BYTE : __ ldsb(s, O7, d); break; - case T_CHAR : __ lduh(s, O7, d); break; - case T_SHORT : __ ldsh(s, O7, d); break; - case T_INT : __ ld(s, O7, d); break; - case T_ADDRESS:// fall through - case T_ARRAY : // fall through - case T_OBJECT: __ ld_ptr(s, O7, d); break; - default : ShouldNotReachHere(); - } - } - if (ld_type == T_ARRAY || ld_type == T_OBJECT) __ verify_oop(d); - return load_offset; -} - - -// store with 32-bit displacement -void LIR_Assembler::store(Register value, Register base, int offset, BasicType type, CodeEmitInfo *info) { - if (Assembler::is_simm13(offset)) { - if (info != NULL) add_debug_info_for_null_check_here(info); - switch (type) { - case T_BOOLEAN: // fall through - case T_BYTE : __ stb(value, base, offset); break; - case T_CHAR : __ sth(value, base, offset); break; - case T_SHORT : __ sth(value, base, offset); break; - case T_INT : __ stw(value, base, offset); break; - case T_ADDRESS:// fall through - case T_ARRAY : // fall through - case T_OBJECT: __ st_ptr(value, base, offset); break; - default : ShouldNotReachHere(); - } - } else { - __ set(offset, O7); - if (info != NULL) add_debug_info_for_null_check_here(info); - switch (type) { - case T_BOOLEAN: // fall through - case T_BYTE : __ stb(value, base, O7); break; - case T_CHAR : __ sth(value, base, O7); break; - case T_SHORT : __ sth(value, base, O7); break; - case T_INT : __ stw(value, base, O7); break; - case T_ADDRESS:// fall through - case T_ARRAY : //fall through - case T_OBJECT: __ st_ptr(value, base, O7); break; - default : ShouldNotReachHere(); - } - } - // Note: Do the store before verification as the code might be patched! - if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(value); -} - - -// load float with 32-bit displacement -void LIR_Assembler::load(Register s, int disp, FloatRegister d, BasicType ld_type, CodeEmitInfo *info) { - FloatRegisterImpl::Width w; - switch(ld_type) { - case T_FLOAT : w = FloatRegisterImpl::S; break; - case T_DOUBLE: w = FloatRegisterImpl::D; break; - default : ShouldNotReachHere(); - } - - if (Assembler::is_simm13(disp)) { - if (info != NULL) add_debug_info_for_null_check_here(info); - if (disp % BytesPerLong != 0 && w == FloatRegisterImpl::D) { - __ ldf(FloatRegisterImpl::S, s, disp + BytesPerWord, d->successor()); - __ ldf(FloatRegisterImpl::S, s, disp , d); - } else { - __ ldf(w, s, disp, d); - } - } else { - __ set(disp, O7); - if (info != NULL) add_debug_info_for_null_check_here(info); - __ ldf(w, s, O7, d); - } -} - - -// store float with 32-bit displacement -void LIR_Assembler::store(FloatRegister value, Register base, int offset, BasicType type, CodeEmitInfo *info) { - FloatRegisterImpl::Width w; - switch(type) { - case T_FLOAT : w = FloatRegisterImpl::S; break; - case T_DOUBLE: w = FloatRegisterImpl::D; break; - default : ShouldNotReachHere(); - } - - if (Assembler::is_simm13(offset)) { - if (info != NULL) add_debug_info_for_null_check_here(info); - if (w == FloatRegisterImpl::D && offset % BytesPerLong != 0) { - __ stf(FloatRegisterImpl::S, value->successor(), base, offset + BytesPerWord); - __ stf(FloatRegisterImpl::S, value , base, offset); - } else { - __ stf(w, value, base, offset); - } - } else { - __ set(offset, O7); - if (info != NULL) add_debug_info_for_null_check_here(info); - __ stf(w, value, O7, base); - } -} - - -int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool unaligned) { +int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool wide, bool unaligned) { int store_offset; if (!Assembler::is_simm13(offset + (type == T_LONG) ? wordSize : 0)) { assert(!unaligned, "can't handle this"); // for offsets larger than a simm13 we setup the offset in O7 __ set(offset, O7); - store_offset = store(from_reg, base, O7, type); + store_offset = store(from_reg, base, O7, type, wide); } else { - if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(from_reg->as_register()); + if (type == T_ARRAY || type == T_OBJECT) { + __ verify_oop(from_reg->as_register()); + } store_offset = code_offset(); switch (type) { case T_BOOLEAN: // fall through @@ -934,9 +818,22 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType __ stw(from_reg->as_register_hi(), base, offset + hi_word_offset_in_bytes); #endif break; - case T_ADDRESS:// fall through + case T_ADDRESS: + __ st_ptr(from_reg->as_register(), base, offset); + break; case T_ARRAY : // fall through - case T_OBJECT: __ st_ptr(from_reg->as_register(), base, offset); break; + case T_OBJECT: + { + if (UseCompressedOops && !wide) { + __ encode_heap_oop(from_reg->as_register(), G3_scratch); + store_offset = code_offset(); + __ stw(G3_scratch, base, offset); + } else { + __ st_ptr(from_reg->as_register(), base, offset); + } + break; + } + case T_FLOAT : __ stf(FloatRegisterImpl::S, from_reg->as_float_reg(), base, offset); break; case T_DOUBLE: { @@ -958,8 +855,10 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType } -int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicType type) { - if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(from_reg->as_register()); +int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicType type, bool wide) { + if (type == T_ARRAY || type == T_OBJECT) { + __ verify_oop(from_reg->as_register()); + } int store_offset = code_offset(); switch (type) { case T_BOOLEAN: // fall through @@ -975,9 +874,21 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicTy __ std(from_reg->as_register_hi(), base, disp); #endif break; - case T_ADDRESS:// fall through + case T_ADDRESS: + __ st_ptr(from_reg->as_register(), base, disp); + break; case T_ARRAY : // fall through - case T_OBJECT: __ st_ptr(from_reg->as_register(), base, disp); break; + case T_OBJECT: + { + if (UseCompressedOops && !wide) { + __ encode_heap_oop(from_reg->as_register(), G3_scratch); + store_offset = code_offset(); + __ stw(G3_scratch, base, disp); + } else { + __ st_ptr(from_reg->as_register(), base, disp); + } + break; + } case T_FLOAT : __ stf(FloatRegisterImpl::S, from_reg->as_float_reg(), base, disp); break; case T_DOUBLE: __ stf(FloatRegisterImpl::D, from_reg->as_double_reg(), base, disp); break; default : ShouldNotReachHere(); @@ -986,14 +897,14 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicTy } -int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool unaligned) { +int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool wide, bool unaligned) { int load_offset; if (!Assembler::is_simm13(offset + (type == T_LONG) ? wordSize : 0)) { assert(base != O7, "destroying register"); assert(!unaligned, "can't handle this"); // for offsets larger than a simm13 we setup the offset in O7 __ set(offset, O7); - load_offset = load(base, O7, to_reg, type); + load_offset = load(base, O7, to_reg, type, wide); } else { load_offset = code_offset(); switch(type) { @@ -1030,9 +941,18 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ #endif } break; - case T_ADDRESS:// fall through + case T_ADDRESS: __ ld_ptr(base, offset, to_reg->as_register()); break; case T_ARRAY : // fall through - case T_OBJECT: __ ld_ptr(base, offset, to_reg->as_register()); break; + case T_OBJECT: + { + if (UseCompressedOops && !wide) { + __ lduw(base, offset, to_reg->as_register()); + __ decode_heap_oop(to_reg->as_register()); + } else { + __ ld_ptr(base, offset, to_reg->as_register()); + } + break; + } case T_FLOAT: __ ldf(FloatRegisterImpl::S, base, offset, to_reg->as_float_reg()); break; case T_DOUBLE: { @@ -1048,23 +968,34 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ } default : ShouldNotReachHere(); } - if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(to_reg->as_register()); + if (type == T_ARRAY || type == T_OBJECT) { + __ verify_oop(to_reg->as_register()); + } } return load_offset; } -int LIR_Assembler::load(Register base, Register disp, LIR_Opr to_reg, BasicType type) { +int LIR_Assembler::load(Register base, Register disp, LIR_Opr to_reg, BasicType type, bool wide) { int load_offset = code_offset(); switch(type) { case T_BOOLEAN: // fall through - case T_BYTE : __ ldsb(base, disp, to_reg->as_register()); break; - case T_CHAR : __ lduh(base, disp, to_reg->as_register()); break; - case T_SHORT : __ ldsh(base, disp, to_reg->as_register()); break; - case T_INT : __ ld(base, disp, to_reg->as_register()); break; - case T_ADDRESS:// fall through + case T_BYTE : __ ldsb(base, disp, to_reg->as_register()); break; + case T_CHAR : __ lduh(base, disp, to_reg->as_register()); break; + case T_SHORT : __ ldsh(base, disp, to_reg->as_register()); break; + case T_INT : __ ld(base, disp, to_reg->as_register()); break; + case T_ADDRESS: __ ld_ptr(base, disp, to_reg->as_register()); break; case T_ARRAY : // fall through - case T_OBJECT: __ ld_ptr(base, disp, to_reg->as_register()); break; + case T_OBJECT: + { + if (UseCompressedOops && !wide) { + __ lduw(base, disp, to_reg->as_register()); + __ decode_heap_oop(to_reg->as_register()); + } else { + __ ld_ptr(base, disp, to_reg->as_register()); + } + break; + } case T_FLOAT: __ ldf(FloatRegisterImpl::S, base, disp, to_reg->as_float_reg()); break; case T_DOUBLE: __ ldf(FloatRegisterImpl::D, base, disp, to_reg->as_double_reg()); break; case T_LONG : @@ -1078,61 +1009,17 @@ int LIR_Assembler::load(Register base, Register disp, LIR_Opr to_reg, BasicType break; default : ShouldNotReachHere(); } - if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(to_reg->as_register()); + if (type == T_ARRAY || type == T_OBJECT) { + __ verify_oop(to_reg->as_register()); + } return load_offset; } - -// load/store with an Address -void LIR_Assembler::load(const Address& a, Register d, BasicType ld_type, CodeEmitInfo *info, int offset) { - load(a.base(), a.disp() + offset, d, ld_type, info); -} - - -void LIR_Assembler::store(Register value, const Address& dest, BasicType type, CodeEmitInfo *info, int offset) { - store(value, dest.base(), dest.disp() + offset, type, info); -} - - -// loadf/storef with an Address -void LIR_Assembler::load(const Address& a, FloatRegister d, BasicType ld_type, CodeEmitInfo *info, int offset) { - load(a.base(), a.disp() + offset, d, ld_type, info); -} - - -void LIR_Assembler::store(FloatRegister value, const Address& dest, BasicType type, CodeEmitInfo *info, int offset) { - store(value, dest.base(), dest.disp() + offset, type, info); -} - - -// load/store with an Address -void LIR_Assembler::load(LIR_Address* a, Register d, BasicType ld_type, CodeEmitInfo *info) { - load(as_Address(a), d, ld_type, info); -} - - -void LIR_Assembler::store(Register value, LIR_Address* dest, BasicType type, CodeEmitInfo *info) { - store(value, as_Address(dest), type, info); -} - - -// loadf/storef with an Address -void LIR_Assembler::load(LIR_Address* a, FloatRegister d, BasicType ld_type, CodeEmitInfo *info) { - load(as_Address(a), d, ld_type, info); -} - - -void LIR_Assembler::store(FloatRegister value, LIR_Address* dest, BasicType type, CodeEmitInfo *info) { - store(value, as_Address(dest), type, info); -} - - void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { LIR_Const* c = src->as_constant_ptr(); switch (c->type()) { case T_INT: - case T_FLOAT: - case T_ADDRESS: { + case T_FLOAT: { Register src_reg = O7; int value = c->as_jint_bits(); if (value == 0) { @@ -1144,6 +1031,18 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { __ stw(src_reg, addr.base(), addr.disp()); break; } + case T_ADDRESS: { + Register src_reg = O7; + int value = c->as_jint_bits(); + if (value == 0) { + src_reg = G0; + } else { + __ set(value, O7); + } + Address addr = frame_map()->address_for_slot(dest->single_stack_ix()); + __ st_ptr(src_reg, addr.base(), addr.disp()); + break; + } case T_OBJECT: { Register src_reg = O7; jobject2reg(c->as_jobject(), src_reg); @@ -1178,14 +1077,12 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { } -void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info ) { +void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide) { LIR_Const* c = src->as_constant_ptr(); LIR_Address* addr = dest->as_address_ptr(); Register base = addr->base()->as_pointer_register(); + int offset = -1; - if (info != NULL) { - add_debug_info_for_null_check_here(info); - } switch (c->type()) { case T_INT: case T_FLOAT: @@ -1199,10 +1096,10 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi } if (addr->index()->is_valid()) { assert(addr->disp() == 0, "must be zero"); - store(tmp, base, addr->index()->as_pointer_register(), type); + offset = store(tmp, base, addr->index()->as_pointer_register(), type, wide); } else { assert(Assembler::is_simm13(addr->disp()), "can't handle larger addresses"); - store(tmp, base, addr->disp(), type); + offset = store(tmp, base, addr->disp(), type, wide, false); } break; } @@ -1212,21 +1109,21 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi assert(Assembler::is_simm13(addr->disp()) && Assembler::is_simm13(addr->disp() + 4), "can't handle larger addresses"); - Register tmp = O7; + LIR_Opr tmp = FrameMap::O7_opr; int value_lo = c->as_jint_lo_bits(); if (value_lo == 0) { - tmp = G0; + tmp = FrameMap::G0_opr; } else { __ set(value_lo, O7); } - store(tmp, base, addr->disp() + lo_word_offset_in_bytes, T_INT); + offset = store(tmp, base, addr->disp() + lo_word_offset_in_bytes, T_INT, wide, false); int value_hi = c->as_jint_hi_bits(); if (value_hi == 0) { - tmp = G0; + tmp = FrameMap::G0_opr; } else { __ set(value_hi, O7); } - store(tmp, base, addr->disp() + hi_word_offset_in_bytes, T_INT); + offset = store(tmp, base, addr->disp() + hi_word_offset_in_bytes, T_INT, wide, false); break; } case T_OBJECT: { @@ -1241,10 +1138,10 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi // handle either reg+reg or reg+disp address if (addr->index()->is_valid()) { assert(addr->disp() == 0, "must be zero"); - store(tmp, base, addr->index()->as_pointer_register(), type); + offset = store(tmp, base, addr->index()->as_pointer_register(), type, wide); } else { assert(Assembler::is_simm13(addr->disp()), "can't handle larger addresses"); - store(tmp, base, addr->disp(), type); + offset = store(tmp, base, addr->disp(), type, wide, false); } break; @@ -1252,6 +1149,10 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi default: Unimplemented(); } + if (info != NULL) { + assert(offset != -1, "offset should've been set"); + add_debug_info_for_null_check(offset, info); + } } @@ -1336,7 +1237,7 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod assert(to_reg->is_single_cpu(), "Must be a cpu register."); __ set(const_addrlit, O7); - load(O7, 0, to_reg->as_register(), T_INT); + __ ld(O7, 0, to_reg->as_register()); } } break; @@ -1429,7 +1330,7 @@ Address LIR_Assembler::as_Address_lo(LIR_Address* addr) { void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type, - LIR_PatchCode patch_code, CodeEmitInfo* info, bool unaligned) { + LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide, bool unaligned) { LIR_Address* addr = src_opr->as_address_ptr(); LIR_Opr to_reg = dest; @@ -1475,16 +1376,15 @@ void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type, assert(disp_reg != noreg || Assembler::is_simm13(disp_value), "should have set this up"); if (disp_reg == noreg) { - offset = load(src, disp_value, to_reg, type, unaligned); + offset = load(src, disp_value, to_reg, type, wide, unaligned); } else { assert(!unaligned, "can't handle this"); - offset = load(src, disp_reg, to_reg, type); + offset = load(src, disp_reg, to_reg, type, wide); } if (patch != NULL) { patching_epilog(patch, patch_code, src, info); } - if (info != NULL) add_debug_info_for_null_check(offset, info); } @@ -1518,7 +1418,7 @@ void LIR_Assembler::stack2reg(LIR_Opr src, LIR_Opr dest, BasicType type) { } bool unaligned = (addr.disp() - STACK_BIAS) % 8 != 0; - load(addr.base(), addr.disp(), dest, dest->type(), unaligned); + load(addr.base(), addr.disp(), dest, dest->type(), true /*wide*/, unaligned); } @@ -1530,7 +1430,7 @@ void LIR_Assembler::reg2stack(LIR_Opr from_reg, LIR_Opr dest, BasicType type, bo addr = frame_map()->address_for_slot(dest->double_stack_ix()); } bool unaligned = (addr.disp() - STACK_BIAS) % 8 != 0; - store(from_reg, addr.base(), addr.disp(), from_reg->type(), unaligned); + store(from_reg, addr.base(), addr.disp(), from_reg->type(), true /*wide*/, unaligned); } @@ -1578,7 +1478,7 @@ void LIR_Assembler::reg2reg(LIR_Opr from_reg, LIR_Opr to_reg) { void LIR_Assembler::reg2mem(LIR_Opr from_reg, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, - bool unaligned) { + bool wide, bool unaligned) { LIR_Address* addr = dest->as_address_ptr(); Register src = addr->base()->as_pointer_register(); @@ -1622,10 +1522,10 @@ void LIR_Assembler::reg2mem(LIR_Opr from_reg, LIR_Opr dest, BasicType type, assert(disp_reg != noreg || Assembler::is_simm13(disp_value), "should have set this up"); if (disp_reg == noreg) { - offset = store(from_reg, src, disp_value, type, unaligned); + offset = store(from_reg, src, disp_value, type, wide, unaligned); } else { assert(!unaligned, "can't handle this"); - offset = store(from_reg, src, disp_reg, type); + offset = store(from_reg, src, disp_reg, type, wide); } if (patch != NULL) { @@ -2184,13 +2084,13 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { // make sure src and dst are non-null and load array length if (flags & LIR_OpArrayCopy::src_null_check) { __ tst(src); - __ br(Assembler::equal, false, Assembler::pn, *stub->entry()); + __ brx(Assembler::equal, false, Assembler::pn, *stub->entry()); __ delayed()->nop(); } if (flags & LIR_OpArrayCopy::dst_null_check) { __ tst(dst); - __ br(Assembler::equal, false, Assembler::pn, *stub->entry()); + __ brx(Assembler::equal, false, Assembler::pn, *stub->entry()); __ delayed()->nop(); } @@ -2232,10 +2132,18 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { } if (flags & LIR_OpArrayCopy::type_check) { - __ ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp); - __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2); - __ cmp(tmp, tmp2); - __ br(Assembler::notEqual, false, Assembler::pt, *stub->entry()); + if (UseCompressedOops) { + // We don't need decode because we just need to compare + __ lduw(src, oopDesc::klass_offset_in_bytes(), tmp); + __ lduw(dst, oopDesc::klass_offset_in_bytes(), tmp2); + __ cmp(tmp, tmp2); + __ br(Assembler::notEqual, false, Assembler::pt, *stub->entry()); + } else { + __ ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp); + __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2); + __ cmp(tmp, tmp2); + __ brx(Assembler::notEqual, false, Assembler::pt, *stub->entry()); + } __ delayed()->nop(); } @@ -2250,20 +2158,44 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { // but not necessarily exactly of type default_type. Label known_ok, halt; jobject2reg(op->expected_type()->constant_encoding(), tmp); - __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2); - if (basic_type != T_OBJECT) { - __ cmp(tmp, tmp2); - __ br(Assembler::notEqual, false, Assembler::pn, halt); - __ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp2); - __ cmp(tmp, tmp2); - __ br(Assembler::equal, false, Assembler::pn, known_ok); - __ delayed()->nop(); + if (UseCompressedOops) { + // tmp holds the default type. It currently comes uncompressed after the + // load of a constant, so encode it. + __ encode_heap_oop(tmp); + // load the raw value of the dst klass, since we will be comparing + // uncompressed values directly. + __ lduw(dst, oopDesc::klass_offset_in_bytes(), tmp2); + if (basic_type != T_OBJECT) { + __ cmp(tmp, tmp2); + __ br(Assembler::notEqual, false, Assembler::pn, halt); + // load the raw value of the src klass. + __ delayed()->lduw(src, oopDesc::klass_offset_in_bytes(), tmp2); + __ cmp(tmp, tmp2); + __ br(Assembler::equal, false, Assembler::pn, known_ok); + __ delayed()->nop(); + } else { + __ cmp(tmp, tmp2); + __ br(Assembler::equal, false, Assembler::pn, known_ok); + __ delayed()->cmp(src, dst); + __ brx(Assembler::equal, false, Assembler::pn, known_ok); + __ delayed()->nop(); + } } else { - __ cmp(tmp, tmp2); - __ br(Assembler::equal, false, Assembler::pn, known_ok); - __ delayed()->cmp(src, dst); - __ br(Assembler::equal, false, Assembler::pn, known_ok); - __ delayed()->nop(); + __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2); + if (basic_type != T_OBJECT) { + __ cmp(tmp, tmp2); + __ brx(Assembler::notEqual, false, Assembler::pn, halt); + __ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp2); + __ cmp(tmp, tmp2); + __ brx(Assembler::equal, false, Assembler::pn, known_ok); + __ delayed()->nop(); + } else { + __ cmp(tmp, tmp2); + __ brx(Assembler::equal, false, Assembler::pn, known_ok); + __ delayed()->cmp(src, dst); + __ brx(Assembler::equal, false, Assembler::pn, known_ok); + __ delayed()->nop(); + } } __ bind(halt); __ stop("incorrect type information in arraycopy"); @@ -2471,7 +2403,7 @@ void LIR_Assembler::type_profile_helper(Register mdo, int mdo_offset_bias, Label next_test; Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)) - mdo_offset_bias); - load(recv_addr, tmp1, T_OBJECT); + __ ld_ptr(recv_addr, tmp1); __ br_notnull(tmp1, false, Assembler::pt, next_test); __ delayed()->nop(); __ st_ptr(recv, recv_addr); @@ -2563,7 +2495,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L // get object class // not a safepoint as obj null check happens earlier - load(obj, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL); + __ load_klass(obj, klass_RInfo); if (op->fast_check()) { assert_different_registers(klass_RInfo, k_RInfo); __ cmp(k_RInfo, klass_RInfo); @@ -2605,7 +2537,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L __ set(mdo_offset_bias, tmp1); __ add(mdo, tmp1, mdo); } - load(Address(obj, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT); + __ load_klass(obj, recv); type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, success); // Jump over the failure case __ ba(false, *success); @@ -2674,11 +2606,12 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { __ br_null(value, false, Assembler::pn, done); __ delayed()->nop(); } - load(array, oopDesc::klass_offset_in_bytes(), k_RInfo, T_OBJECT, op->info_for_exception()); - load(value, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL); + add_debug_info_for_null_check_here(op->info_for_exception()); + __ load_klass(array, k_RInfo); + __ load_klass(value, klass_RInfo); // get instance klass - load(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc), k_RInfo, T_OBJECT, NULL); + __ ld_ptr(Address(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)), k_RInfo); // perform the fast part of the checking logic __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, success_target, failure_target, NULL); @@ -2700,7 +2633,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { __ set(mdo_offset_bias, tmp1); __ add(mdo, tmp1, mdo); } - load(Address(value, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT); + __ load_klass(value, recv); type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, &done); __ ba(false, done); __ delayed()->nop(); @@ -2781,14 +2714,17 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { Register t2 = op->tmp2()->as_register(); __ mov(cmp_value, t1); __ mov(new_value, t2); -#ifdef _LP64 if (op->code() == lir_cas_obj) { - __ casx(addr, t1, t2); - } else -#endif - { + if (UseCompressedOops) { + __ encode_heap_oop(t1); + __ encode_heap_oop(t2); __ cas(addr, t1, t2); + } else { + __ casx(addr, t1, t2); } + } else { + __ cas(addr, t1, t2); + } __ cmp(t1, t2); } else { Unimplemented(); @@ -2966,7 +2902,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { } } } else { - load(Address(recv, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT); + __ load_klass(recv, recv); Label update_done; type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, &update_done); // Receiver did not match any saved receiver and there is no empty row for it. @@ -3160,7 +3096,7 @@ void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, } else { // use normal move for all other volatiles since they don't need // special handling to remain atomic. - move_op(src, dest, type, lir_patch_none, info, false, false); + move_op(src, dest, type, lir_patch_none, info, false, false, false); } } diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp index ffcd5b494e9..386159c89b8 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp @@ -40,33 +40,11 @@ // and then a load or store is emitted with ([O7] + [d]). // - // some load/store variants return the code_offset for proper positioning of debug info for null checks + int store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool wide, bool unaligned); + int store(LIR_Opr from_reg, Register base, Register disp, BasicType type, bool wide); - // load/store with 32 bit displacement - int load(Register s, int disp, Register d, BasicType ld_type, CodeEmitInfo* info = NULL); - void store(Register value, Register base, int offset, BasicType type, CodeEmitInfo *info = NULL); - - // loadf/storef with 32 bit displacement - void load(Register s, int disp, FloatRegister d, BasicType ld_type, CodeEmitInfo* info = NULL); - void store(FloatRegister d, Register s1, int disp, BasicType st_type, CodeEmitInfo* info = NULL); - - // convienence methods for calling load/store with an Address - void load(const Address& a, Register d, BasicType ld_type, CodeEmitInfo* info = NULL, int offset = 0); - void store(Register d, const Address& a, BasicType st_type, CodeEmitInfo* info = NULL, int offset = 0); - void load(const Address& a, FloatRegister d, BasicType ld_type, CodeEmitInfo* info = NULL, int offset = 0); - void store(FloatRegister d, const Address& a, BasicType st_type, CodeEmitInfo* info = NULL, int offset = 0); - - // convienence methods for calling load/store with an LIR_Address - void load(LIR_Address* a, Register d, BasicType ld_type, CodeEmitInfo* info = NULL); - void store(Register d, LIR_Address* a, BasicType st_type, CodeEmitInfo* info = NULL); - void load(LIR_Address* a, FloatRegister d, BasicType ld_type, CodeEmitInfo* info = NULL); - void store(FloatRegister d, LIR_Address* a, BasicType st_type, CodeEmitInfo* info = NULL); - - int store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool unaligned = false); - int store(LIR_Opr from_reg, Register base, Register disp, BasicType type); - - int load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool unaligned = false); - int load(Register base, Register disp, LIR_Opr to_reg, BasicType type); + int load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool wide, bool unaligned); + int load(Register base, Register disp, LIR_Opr to_reg, BasicType type, bool wide); void monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register hdr, int monitor_no); diff --git a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp index 6d9f9de5286..6340156f779 100644 --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp @@ -40,7 +40,7 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { const Register temp_reg = G3_scratch; // Note: needs more testing of out-of-line vs. inline slow case verify_oop(receiver); - ld_ptr(receiver, oopDesc::klass_offset_in_bytes(), temp_reg); + load_klass(receiver, temp_reg); cmp(temp_reg, iCache); brx(Assembler::equal, true, Assembler::pt, L); delayed()->nop(); @@ -185,9 +185,19 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register } else { set((intx)markOopDesc::prototype(), t1); } - st_ptr(t1 , obj, oopDesc::mark_offset_in_bytes ()); - st_ptr(klass, obj, oopDesc::klass_offset_in_bytes ()); - if (len->is_valid()) st(len , obj, arrayOopDesc::length_offset_in_bytes()); + st_ptr(t1, obj, oopDesc::mark_offset_in_bytes()); + if (UseCompressedOops) { + // Save klass + mov(klass, t1); + encode_heap_oop_not_null(t1); + stw(t1, obj, oopDesc::klass_offset_in_bytes()); + } else { + st_ptr(klass, obj, oopDesc::klass_offset_in_bytes()); + } + if (len->is_valid()) st(len, obj, arrayOopDesc::length_offset_in_bytes()); + else if (UseCompressedOops) { + store_klass_gap(G0, obj); + } } @@ -235,7 +245,7 @@ void C1_MacroAssembler::initialize_object( Register t1, // temp register Register t2 // temp register ) { - const int hdr_size_in_bytes = instanceOopDesc::base_offset_in_bytes(); + const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize; initialize_header(obj, klass, noreg, t1, t2); diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index 127cc9ab316..7dabe35c23e 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -612,7 +612,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { // load the klass and check the has finalizer flag Label register_finalizer; Register t = O1; - __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), t); + __ load_klass(O0, t); __ ld(t, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc), t); __ set(JVM_ACC_HAS_FINALIZER, G3); __ andcc(G3, t, G0); diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index d4bf4b422ec..b63a3ca4302 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -135,6 +135,7 @@ REGISTER_DECLARATION(Register, r15_thread, r15); // callee-saved // Using noreg ensures if the dead code is incorrectly live and executed it // will cause an assertion failure #define rscratch1 noreg +#define rscratch2 noreg #endif // _LP64 diff --git a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp index e8de24a5552..62088bd100e 100644 --- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp @@ -483,7 +483,7 @@ void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { Register pre_val_reg = pre_val()->as_register(); - ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false); + ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/); __ cmpptr(pre_val_reg, (int32_t) NULL_WORD); __ jcc(Assembler::equal, _continuation); diff --git a/hotspot/src/cpu/x86/vm/c1_Defs_x86.hpp b/hotspot/src/cpu/x86/vm/c1_Defs_x86.hpp index 883fa166336..dab876adc8a 100644 --- a/hotspot/src/cpu/x86/vm/c1_Defs_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c1_Defs_x86.hpp @@ -61,8 +61,8 @@ enum { pd_nof_xmm_regs_linearscan = pd_nof_xmm_regs_frame_map, // number of registers visible to linear scan pd_first_cpu_reg = 0, pd_last_cpu_reg = NOT_LP64(5) LP64_ONLY(11), - pd_first_byte_reg = 2, - pd_last_byte_reg = 5, + pd_first_byte_reg = NOT_LP64(2) LP64_ONLY(0), + pd_last_byte_reg = NOT_LP64(5) LP64_ONLY(11), pd_first_fpu_reg = pd_nof_cpu_regs_frame_map, pd_last_fpu_reg = pd_first_fpu_reg + 7, pd_first_xmm_reg = pd_nof_cpu_regs_frame_map + pd_nof_fpu_regs_frame_map, diff --git a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp index bc5037404a3..52f42977f71 100644 --- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp @@ -158,9 +158,11 @@ void FrameMap::initialize() { map_register( 6, r8); r8_opr = LIR_OprFact::single_cpu(6); map_register( 7, r9); r9_opr = LIR_OprFact::single_cpu(7); map_register( 8, r11); r11_opr = LIR_OprFact::single_cpu(8); - map_register( 9, r12); r12_opr = LIR_OprFact::single_cpu(9); - map_register(10, r13); r13_opr = LIR_OprFact::single_cpu(10); - map_register(11, r14); r14_opr = LIR_OprFact::single_cpu(11); + map_register( 9, r13); r13_opr = LIR_OprFact::single_cpu(9); + map_register(10, r14); r14_opr = LIR_OprFact::single_cpu(10); + // r12 is allocated conditionally. With compressed oops it holds + // the heapbase value and is not visible to the allocator. + map_register(11, r12); r12_opr = LIR_OprFact::single_cpu(11); // The unallocatable registers are at the end map_register(12, r10); r10_opr = LIR_OprFact::single_cpu(12); map_register(13, r15); r15_opr = LIR_OprFact::single_cpu(13); @@ -191,9 +193,9 @@ void FrameMap::initialize() { _caller_save_cpu_regs[6] = r8_opr; _caller_save_cpu_regs[7] = r9_opr; _caller_save_cpu_regs[8] = r11_opr; - _caller_save_cpu_regs[9] = r12_opr; - _caller_save_cpu_regs[10] = r13_opr; - _caller_save_cpu_regs[11] = r14_opr; + _caller_save_cpu_regs[9] = r13_opr; + _caller_save_cpu_regs[10] = r14_opr; + _caller_save_cpu_regs[11] = r12_opr; #endif // _LP64 diff --git a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp index 17f2386c0ba..642701c2831 100644 --- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp @@ -130,4 +130,15 @@ return _caller_save_xmm_regs[i]; } + static int adjust_reg_range(int range) { + // Reduce the number of available regs (to free r12) in case of compressed oops + if (UseCompressedOops) return range - 1; + return range; + } + + static int nof_caller_save_cpu_regs() { return adjust_reg_range(pd_nof_caller_save_cpu_regs_frame_map); } + static int last_cpu_reg() { return adjust_reg_range(pd_last_cpu_reg); } + static int last_byte_reg() { return adjust_reg_range(pd_last_byte_reg); } + #endif // CPU_X86_VM_C1_FRAMEMAP_X86_HPP + diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 8c15f1926e5..4daac1aafc4 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -343,8 +343,8 @@ int LIR_Assembler::check_icache() { Register receiver = FrameMap::receiver_opr->as_register(); Register ic_klass = IC_Klass; const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9); - - if (!VerifyOops) { + const bool do_post_padding = VerifyOops || UseCompressedOops; + if (!do_post_padding) { // insert some nops so that the verified entry point is aligned on CodeEntryAlignment while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) { __ nop(); @@ -352,8 +352,8 @@ int LIR_Assembler::check_icache() { } int offset = __ offset(); __ inline_cache_check(receiver, IC_Klass); - assert(__ offset() % CodeEntryAlignment == 0 || VerifyOops, "alignment must be correct"); - if (VerifyOops) { + assert(__ offset() % CodeEntryAlignment == 0 || do_post_padding, "alignment must be correct"); + if (do_post_padding) { // force alignment after the cache check. // It's been verified to be aligned if !VerifyOops __ align(CodeEntryAlignment); @@ -559,16 +559,16 @@ void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst, __ movptr (rax, arg1->as_register()); // Get addresses of first characters from both Strings - __ movptr (rsi, Address(rax, java_lang_String::value_offset_in_bytes())); - __ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes())); - __ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); + __ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes())); + __ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes())); + __ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); // rbx, may be NULL add_debug_info_for_null_check_here(info); - __ movptr (rdi, Address(rbx, java_lang_String::value_offset_in_bytes())); - __ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes())); - __ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); + __ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes())); + __ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes())); + __ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); // compute minimum length (in rax) and difference of lengths (on top of stack) if (VM_Version::supports_cmov()) { @@ -696,13 +696,18 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod LIR_Const* c = src->as_constant_ptr(); switch (c->type()) { - case T_INT: - case T_ADDRESS: { + case T_INT: { assert(patch_code == lir_patch_none, "no patching handled here"); __ movl(dest->as_register(), c->as_jint()); break; } + case T_ADDRESS: { + assert(patch_code == lir_patch_none, "no patching handled here"); + __ movptr(dest->as_register(), c->as_jint()); + break; + } + case T_LONG: { assert(patch_code == lir_patch_none, "no patching handled here"); #ifdef _LP64 @@ -780,10 +785,13 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { switch (c->type()) { case T_INT: // fall through case T_FLOAT: - case T_ADDRESS: __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits()); break; + case T_ADDRESS: + __ movptr(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits()); + break; + case T_OBJECT: __ movoop(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jobject()); break; @@ -806,7 +814,7 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { } } -void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info ) { +void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide) { assert(src->is_constant(), "should not call otherwise"); assert(dest->is_address(), "should not call otherwise"); LIR_Const* c = src->as_constant_ptr(); @@ -816,14 +824,21 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi switch (type) { case T_INT: // fall through case T_FLOAT: - case T_ADDRESS: __ movl(as_Address(addr), c->as_jint_bits()); break; + case T_ADDRESS: + __ movptr(as_Address(addr), c->as_jint_bits()); + break; + case T_OBJECT: // fall through case T_ARRAY: if (c->as_jobject() == NULL) { - __ movptr(as_Address(addr), NULL_WORD); + if (UseCompressedOops && !wide) { + __ movl(as_Address(addr), (int32_t)NULL_WORD); + } else { + __ movptr(as_Address(addr), NULL_WORD); + } } else { if (is_literal_address(addr)) { ShouldNotReachHere(); @@ -831,8 +846,14 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi } else { #ifdef _LP64 __ movoop(rscratch1, c->as_jobject()); - null_check_here = code_offset(); - __ movptr(as_Address_lo(addr), rscratch1); + if (UseCompressedOops && !wide) { + __ encode_heap_oop(rscratch1); + null_check_here = code_offset(); + __ movl(as_Address_lo(addr), rscratch1); + } else { + null_check_here = code_offset(); + __ movptr(as_Address_lo(addr), rscratch1); + } #else __ movoop(as_Address(addr), c->as_jobject()); #endif @@ -1009,22 +1030,28 @@ void LIR_Assembler::reg2stack(LIR_Opr src, LIR_Opr dest, BasicType type, bool po } -void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool /* unaligned */) { +void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool wide, bool /* unaligned */) { LIR_Address* to_addr = dest->as_address_ptr(); PatchingStub* patch = NULL; + Register compressed_src = rscratch1; if (type == T_ARRAY || type == T_OBJECT) { __ verify_oop(src->as_register()); +#ifdef _LP64 + if (UseCompressedOops && !wide) { + __ movptr(compressed_src, src->as_register()); + __ encode_heap_oop(compressed_src); + } +#endif } + if (patch_code != lir_patch_none) { patch = new PatchingStub(_masm, PatchingStub::access_field_id); Address toa = as_Address(to_addr); assert(toa.disp() != 0, "must have"); } - if (info != NULL) { - add_debug_info_for_null_check_here(info); - } + int null_check_here = code_offset(); switch (type) { case T_FLOAT: { if (src->is_single_xmm()) { @@ -1050,13 +1077,17 @@ void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch break; } - case T_ADDRESS: // fall through case T_ARRAY: // fall through case T_OBJECT: // fall through -#ifdef _LP64 + if (UseCompressedOops && !wide) { + __ movl(as_Address(to_addr), compressed_src); + } else { + __ movptr(as_Address(to_addr), src->as_register()); + } + break; + case T_ADDRESS: __ movptr(as_Address(to_addr), src->as_register()); break; -#endif // _LP64 case T_INT: __ movl(as_Address(to_addr), src->as_register()); break; @@ -1113,6 +1144,9 @@ void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch default: ShouldNotReachHere(); } + if (info != NULL) { + add_debug_info_for_null_check(null_check_here, info); + } if (patch_code != lir_patch_none) { patching_epilog(patch, patch_code, to_addr->base()->as_register(), info); @@ -1196,7 +1230,7 @@ void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) { } -void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool /* unaligned */) { +void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide, bool /* unaligned */) { assert(src->is_address(), "should not call otherwise"); assert(dest->is_register(), "should not call otherwise"); @@ -1250,13 +1284,18 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch break; } - case T_ADDRESS: // fall through case T_OBJECT: // fall through case T_ARRAY: // fall through -#ifdef _LP64 + if (UseCompressedOops && !wide) { + __ movl(dest->as_register(), from_addr); + } else { + __ movptr(dest->as_register(), from_addr); + } + break; + + case T_ADDRESS: __ movptr(dest->as_register(), from_addr); break; -#endif // _L64 case T_INT: __ movl(dest->as_register(), from_addr); break; @@ -1351,6 +1390,11 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch } if (type == T_ARRAY || type == T_OBJECT) { +#ifdef _LP64 + if (UseCompressedOops && !wide) { + __ decode_heap_oop(dest->as_register()); + } +#endif __ verify_oop(dest->as_register()); } } @@ -1690,7 +1734,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L } else if (obj == klass_RInfo) { klass_RInfo = dst; } - if (k->is_loaded()) { + if (k->is_loaded() && !UseCompressedOops) { select_different_registers(obj, dst, k_RInfo, klass_RInfo); } else { Rtmp1 = op->tmp3()->as_register(); @@ -1727,21 +1771,26 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L if (op->fast_check()) { // get object class // not a safepoint as obj null check happens earlier - if (k->is_loaded()) { #ifdef _LP64 - __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); -#else - __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding()); -#endif // _LP64 + if (UseCompressedOops) { + __ load_klass(Rtmp1, obj); + __ cmpptr(k_RInfo, Rtmp1); } else { __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); } +#else + if (k->is_loaded()) { + __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding()); + } else { + __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); + } +#endif __ jcc(Assembler::notEqual, *failure_target); // successful cast, fall through to profile or jump } else { // get object class // not a safepoint as obj null check happens earlier - __ movptr(klass_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); + __ load_klass(klass_RInfo, obj); if (k->is_loaded()) { // See if we get an immediate positive hit #ifdef _LP64 @@ -1796,7 +1845,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L Register mdo = klass_RInfo, recv = k_RInfo; __ bind(profile_cast_success); __ movoop(mdo, md->constant_encoding()); - __ movptr(recv, Address(obj, oopDesc::klass_offset_in_bytes())); + __ load_klass(recv, obj); Label update_done; type_profile_helper(mdo, md, data, recv, success); __ jmp(*success); @@ -1860,10 +1909,10 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { } add_debug_info_for_null_check_here(op->info_for_exception()); - __ movptr(k_RInfo, Address(array, oopDesc::klass_offset_in_bytes())); - __ movptr(klass_RInfo, Address(value, oopDesc::klass_offset_in_bytes())); + __ load_klass(k_RInfo, array); + __ load_klass(klass_RInfo, value); - // get instance klass + // get instance klass (it's already uncompressed) __ movptr(k_RInfo, Address(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc))); // perform the fast part of the checking logic __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, NULL); @@ -1882,7 +1931,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { Register mdo = klass_RInfo, recv = k_RInfo; __ bind(profile_cast_success); __ movoop(mdo, md->constant_encoding()); - __ movptr(recv, Address(value, oopDesc::klass_offset_in_bytes())); + __ load_klass(recv, value); Label update_done; type_profile_helper(mdo, md, data, recv, &done); __ jmpb(done); @@ -1946,12 +1995,32 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { assert(cmpval != newval, "cmp and new values must be in different registers"); assert(cmpval != addr, "cmp and addr must be in different registers"); assert(newval != addr, "new value and addr must be in different registers"); - if (os::is_MP()) { - __ lock(); - } + if ( op->code() == lir_cas_obj) { - __ cmpxchgptr(newval, Address(addr, 0)); - } else if (op->code() == lir_cas_int) { +#ifdef _LP64 + if (UseCompressedOops) { + __ mov(rscratch1, cmpval); + __ encode_heap_oop(cmpval); + __ mov(rscratch2, newval); + __ encode_heap_oop(rscratch2); + if (os::is_MP()) { + __ lock(); + } + __ cmpxchgl(rscratch2, Address(addr, 0)); + __ mov(cmpval, rscratch1); + } else +#endif + { + if (os::is_MP()) { + __ lock(); + } + __ cmpxchgptr(newval, Address(addr, 0)); + } + } else { + assert(op->code() == lir_cas_int, "lir_cas_int expected"); + if (os::is_MP()) { + __ lock(); + } __ cmpxchgl(newval, Address(addr, 0)); } #ifdef _LP64 @@ -3193,8 +3262,13 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { } if (flags & LIR_OpArrayCopy::type_check) { - __ movptr(tmp, src_klass_addr); - __ cmpptr(tmp, dst_klass_addr); + if (UseCompressedOops) { + __ movl(tmp, src_klass_addr); + __ cmpl(tmp, dst_klass_addr); + } else { + __ movptr(tmp, src_klass_addr); + __ cmpptr(tmp, dst_klass_addr); + } __ jcc(Assembler::notEqual, *stub->entry()); } @@ -3209,13 +3283,23 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { // but not necessarily exactly of type default_type. Label known_ok, halt; __ movoop(tmp, default_type->constant_encoding()); +#ifdef _LP64 + if (UseCompressedOops) { + __ encode_heap_oop(tmp); + } +#endif + if (basic_type != T_OBJECT) { - __ cmpptr(tmp, dst_klass_addr); + + if (UseCompressedOops) __ cmpl(tmp, dst_klass_addr); + else __ cmpptr(tmp, dst_klass_addr); __ jcc(Assembler::notEqual, halt); - __ cmpptr(tmp, src_klass_addr); + if (UseCompressedOops) __ cmpl(tmp, src_klass_addr); + else __ cmpptr(tmp, src_klass_addr); __ jcc(Assembler::equal, known_ok); } else { - __ cmpptr(tmp, dst_klass_addr); + if (UseCompressedOops) __ cmpl(tmp, dst_klass_addr); + else __ cmpptr(tmp, dst_klass_addr); __ jcc(Assembler::equal, known_ok); __ cmpptr(src, dst); __ jcc(Assembler::equal, known_ok); @@ -3344,7 +3428,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { } } } else { - __ movptr(recv, Address(recv, oopDesc::klass_offset_in_bytes())); + __ load_klass(recv, recv); Label update_done; type_profile_helper(mdo, md, data, recv, &update_done); // Receiver did not match any saved receiver and there is no empty row for it. diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp index cf2cd56463b..d75f0b2068c 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -1151,9 +1151,12 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception); } LIR_Opr reg = rlock_result(x); + LIR_Opr tmp3 = LIR_OprFact::illegalOpr; + if (!x->klass()->is_loaded() || UseCompressedOops) { + tmp3 = new_register(objectType); + } __ checkcast(reg, obj.result(), x->klass(), - new_register(objectType), new_register(objectType), - !x->klass()->is_loaded() ? new_register(objectType) : LIR_OprFact::illegalOpr, + new_register(objectType), new_register(objectType), tmp3, x->direct_compare(), info_for_exception, patching_info, stub, x->profiled_method(), x->profiled_bci()); } @@ -1170,9 +1173,12 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) { patching_info = state_for(x, x->state_before()); } obj.load_item(); + LIR_Opr tmp3 = LIR_OprFact::illegalOpr; + if (!x->klass()->is_loaded() || UseCompressedOops) { + tmp3 = new_register(objectType); + } __ instanceof(reg, obj.result(), x->klass(), - new_register(objectType), new_register(objectType), - !x->klass()->is_loaded() ? new_register(objectType) : LIR_OprFact::illegalOpr, + new_register(objectType), new_register(objectType), tmp3, x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci()); } diff --git a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp index 88d15e50d86..efb2002fd65 100644 --- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp @@ -31,18 +31,17 @@ inline bool LinearScan::is_processed_reg_num(int reg_num) { assert(FrameMap::rsp_opr->cpu_regnr() == 6, "wrong assumption below"); assert(FrameMap::rbp_opr->cpu_regnr() == 7, "wrong assumption below"); assert(reg_num >= 0, "invalid reg_num"); - - return reg_num < 6 || reg_num > 7; #else - // rsp and rbp, r10, r15 (numbers 6 ancd 7) are ignored + // rsp and rbp, r10, r15 (numbers [12,15]) are ignored + // r12 (number 11) is conditional on compressed oops. + assert(FrameMap::r12_opr->cpu_regnr() == 11, "wrong assumption below"); assert(FrameMap::r10_opr->cpu_regnr() == 12, "wrong assumption below"); assert(FrameMap::r15_opr->cpu_regnr() == 13, "wrong assumption below"); assert(FrameMap::rsp_opr->cpu_regnrLo() == 14, "wrong assumption below"); assert(FrameMap::rbp_opr->cpu_regnrLo() == 15, "wrong assumption below"); assert(reg_num >= 0, "invalid reg_num"); - - return reg_num < 12 || reg_num > 15; #endif // _LP64 + return reg_num <= FrameMap::last_cpu_reg() || reg_num >= pd_nof_cpu_regs_frame_map; } inline int LinearScan::num_physical_regs(BasicType type) { @@ -104,7 +103,7 @@ inline bool LinearScanWalker::pd_init_regs_for_alloc(Interval* cur) { if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::byte_reg)) { assert(cur->type() != T_FLOAT && cur->type() != T_DOUBLE, "cpu regs only"); _first_reg = pd_first_byte_reg; - _last_reg = pd_last_byte_reg; + _last_reg = FrameMap::last_byte_reg(); return true; } else if ((UseSSE >= 1 && cur->type() == T_FLOAT) || (UseSSE >= 2 && cur->type() == T_DOUBLE)) { _first_reg = pd_first_xmm_reg; diff --git a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp index de6e2e58108..48d117b3fd5 100644 --- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp @@ -155,11 +155,26 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register // This assumes that all prototype bits fit in an int32_t movptr(Address(obj, oopDesc::mark_offset_in_bytes ()), (int32_t)(intptr_t)markOopDesc::prototype()); } +#ifdef _LP64 + if (UseCompressedOops) { // Take care not to kill klass + movptr(t1, klass); + encode_heap_oop_not_null(t1); + movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1); + } else +#endif + { + movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass); + } - movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass); if (len->is_valid()) { movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len); } +#ifdef _LP64 + else if (UseCompressedOops) { + xorptr(t1, t1); + store_klass_gap(obj, t1); + } +#endif } @@ -230,7 +245,7 @@ void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2) { assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "con_size_in_bytes is not multiple of alignment"); - const int hdr_size_in_bytes = instanceOopDesc::base_offset_in_bytes(); + const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize; initialize_header(obj, klass, noreg, t1, t2); @@ -317,13 +332,19 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { // check against inline cache assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check"); int start_offset = offset(); - cmpptr(iCache, Address(receiver, oopDesc::klass_offset_in_bytes())); + + if (UseCompressedOops) { + load_klass(rscratch1, receiver); + cmpptr(rscratch1, iCache); + } else { + cmpptr(iCache, Address(receiver, oopDesc::klass_offset_in_bytes())); + } // if icache check fails, then jump to runtime routine // Note: RECEIVER must still contain the receiver! jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub())); const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9); - assert(offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry"); + assert(UseCompressedOops || offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry"); } diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp index 23afb8267d0..ce51fea3add 100644 --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -1261,7 +1261,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { // load the klass and check the has finalizer flag Label register_finalizer; Register t = rsi; - __ movptr(t, Address(rax, oopDesc::klass_offset_in_bytes())); + __ load_klass(t, rax); __ movl(t, Address(t, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc))); __ testl(t, JVM_ACC_HAS_FINALIZER); __ jcc(Assembler::notZero, register_finalizer); diff --git a/hotspot/src/share/vm/c1/c1_FrameMap.hpp b/hotspot/src/share/vm/c1/c1_FrameMap.hpp index 91ee545e739..c112ad54006 100644 --- a/hotspot/src/share/vm/c1/c1_FrameMap.hpp +++ b/hotspot/src/share/vm/c1/c1_FrameMap.hpp @@ -76,8 +76,8 @@ class FrameMap : public CompilationResourceObj { nof_cpu_regs_reg_alloc = pd_nof_cpu_regs_reg_alloc, nof_fpu_regs_reg_alloc = pd_nof_fpu_regs_reg_alloc, - nof_caller_save_cpu_regs = pd_nof_caller_save_cpu_regs_frame_map, - nof_caller_save_fpu_regs = pd_nof_caller_save_fpu_regs_frame_map, + max_nof_caller_save_cpu_regs = pd_nof_caller_save_cpu_regs_frame_map, + nof_caller_save_fpu_regs = pd_nof_caller_save_fpu_regs_frame_map, spill_slot_size_in_bytes = 4 }; @@ -97,7 +97,7 @@ class FrameMap : public CompilationResourceObj { static Register _cpu_rnr2reg [nof_cpu_regs]; static int _cpu_reg2rnr [nof_cpu_regs]; - static LIR_Opr _caller_save_cpu_regs [nof_caller_save_cpu_regs]; + static LIR_Opr _caller_save_cpu_regs [max_nof_caller_save_cpu_regs]; static LIR_Opr _caller_save_fpu_regs [nof_caller_save_fpu_regs]; int _framesize; @@ -243,7 +243,7 @@ class FrameMap : public CompilationResourceObj { VMReg regname(LIR_Opr opr) const; static LIR_Opr caller_save_cpu_reg_at(int i) { - assert(i >= 0 && i < nof_caller_save_cpu_regs, "out of bounds"); + assert(i >= 0 && i < max_nof_caller_save_cpu_regs, "out of bounds"); return _caller_save_cpu_regs[i]; } diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 81239201cb9..492e21f4d08 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -2795,7 +2795,7 @@ void GraphBuilder::setup_osr_entry_block() { get = append(new UnsafeGetRaw(as_BasicType(local->type()), e, append(new Constant(new IntConstant(offset))), 0, - true)); + true /*unaligned*/, true /*wide*/)); } _state->store_local(index, get); } diff --git a/hotspot/src/share/vm/c1/c1_Instruction.hpp b/hotspot/src/share/vm/c1/c1_Instruction.hpp index 43e8f87e71f..63b30819c7f 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.hpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp @@ -2110,20 +2110,23 @@ BASE(UnsafeRawOp, UnsafeOp) LEAF(UnsafeGetRaw, UnsafeRawOp) private: - bool _may_be_unaligned; // For OSREntry + bool _may_be_unaligned, _is_wide; // For OSREntry public: - UnsafeGetRaw(BasicType basic_type, Value addr, bool may_be_unaligned) + UnsafeGetRaw(BasicType basic_type, Value addr, bool may_be_unaligned, bool is_wide = false) : UnsafeRawOp(basic_type, addr, false) { _may_be_unaligned = may_be_unaligned; + _is_wide = is_wide; } - UnsafeGetRaw(BasicType basic_type, Value base, Value index, int log2_scale, bool may_be_unaligned) + UnsafeGetRaw(BasicType basic_type, Value base, Value index, int log2_scale, bool may_be_unaligned, bool is_wide = false) : UnsafeRawOp(basic_type, base, index, log2_scale, false) { _may_be_unaligned = may_be_unaligned; + _is_wide = is_wide; } - bool may_be_unaligned() { return _may_be_unaligned; } + bool may_be_unaligned() { return _may_be_unaligned; } + bool is_wide() { return _is_wide; } }; diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index e26a176d859..bce59a55d9d 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -1742,6 +1742,8 @@ const char * LIR_Op1::name() const { return "unaligned move"; case lir_move_volatile: return "volatile_move"; + case lir_move_wide: + return "wide_move"; default: ShouldNotReachHere(); return "illegal_op"; diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index 2b8fb7110c5..7a3574cfa95 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -985,6 +985,7 @@ enum LIR_MoveKind { lir_move_normal, lir_move_volatile, lir_move_unaligned, + lir_move_wide, lir_move_max_flag }; @@ -1932,7 +1933,20 @@ class LIR_List: public CompilationResourceObj { void move(LIR_Opr src, LIR_Opr dst, CodeEmitInfo* info = NULL) { append(new LIR_Op1(lir_move, src, dst, dst->type(), lir_patch_none, info)); } void move(LIR_Address* src, LIR_Opr dst, CodeEmitInfo* info = NULL) { append(new LIR_Op1(lir_move, LIR_OprFact::address(src), dst, src->type(), lir_patch_none, info)); } void move(LIR_Opr src, LIR_Address* dst, CodeEmitInfo* info = NULL) { append(new LIR_Op1(lir_move, src, LIR_OprFact::address(dst), dst->type(), lir_patch_none, info)); } - + void move_wide(LIR_Address* src, LIR_Opr dst, CodeEmitInfo* info = NULL) { + if (UseCompressedOops) { + append(new LIR_Op1(lir_move, LIR_OprFact::address(src), dst, src->type(), lir_patch_none, info, lir_move_wide)); + } else { + move(src, dst, info); + } + } + void move_wide(LIR_Opr src, LIR_Address* dst, CodeEmitInfo* info = NULL) { + if (UseCompressedOops) { + append(new LIR_Op1(lir_move, src, LIR_OprFact::address(dst), dst->type(), lir_patch_none, info, lir_move_wide)); + } else { + move(src, dst, info); + } + } void volatile_move(LIR_Opr src, LIR_Opr dst, BasicType type, CodeEmitInfo* info = NULL, LIR_PatchCode patch_code = lir_patch_none) { append(new LIR_Op1(lir_move, src, dst, type, patch_code, info, lir_move_volatile)); } void oop2reg (jobject o, LIR_Opr reg) { append(new LIR_Op1(lir_move, LIR_OprFact::oopConst(o), reg)); } diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp index 153ff3f86b0..c422819974a 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp @@ -489,7 +489,9 @@ void LIR_Assembler::emit_op1(LIR_Op1* op) { volatile_move_op(op->in_opr(), op->result_opr(), op->type(), op->info()); } else { move_op(op->in_opr(), op->result_opr(), op->type(), - op->patch_code(), op->info(), op->pop_fpu_stack(), op->move_kind() == lir_move_unaligned); + op->patch_code(), op->info(), op->pop_fpu_stack(), + op->move_kind() == lir_move_unaligned, + op->move_kind() == lir_move_wide); } break; @@ -758,7 +760,7 @@ void LIR_Assembler::roundfp_op(LIR_Opr src, LIR_Opr tmp, LIR_Opr dest, bool pop_ } -void LIR_Assembler::move_op(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned) { +void LIR_Assembler::move_op(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned, bool wide) { if (src->is_register()) { if (dest->is_register()) { assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here"); @@ -767,7 +769,7 @@ void LIR_Assembler::move_op(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here"); reg2stack(src, dest, type, pop_fpu_stack); } else if (dest->is_address()) { - reg2mem(src, dest, type, patch_code, info, pop_fpu_stack, unaligned); + reg2mem(src, dest, type, patch_code, info, pop_fpu_stack, wide, unaligned); } else { ShouldNotReachHere(); } @@ -790,13 +792,13 @@ void LIR_Assembler::move_op(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch const2stack(src, dest); } else if (dest->is_address()) { assert(patch_code == lir_patch_none, "no patching allowed here"); - const2mem(src, dest, type, info); + const2mem(src, dest, type, info, wide); } else { ShouldNotReachHere(); } } else if (src->is_address()) { - mem2reg(src, dest, type, patch_code, info, unaligned); + mem2reg(src, dest, type, patch_code, info, wide, unaligned); } else { ShouldNotReachHere(); diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 5ddc52c522e..24f62862cdf 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -165,15 +165,17 @@ class LIR_Assembler: public CompilationResourceObj { void const2reg (LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info); void const2stack(LIR_Opr src, LIR_Opr dest); - void const2mem (LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info); + void const2mem (LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide); void reg2stack (LIR_Opr src, LIR_Opr dest, BasicType type, bool pop_fpu_stack); void reg2reg (LIR_Opr src, LIR_Opr dest); - void reg2mem (LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned); + void reg2mem (LIR_Opr src, LIR_Opr dest, BasicType type, + LIR_PatchCode patch_code, CodeEmitInfo* info, + bool pop_fpu_stack, bool wide, bool unaligned); void stack2reg (LIR_Opr src, LIR_Opr dest, BasicType type); void stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type); void mem2reg (LIR_Opr src, LIR_Opr dest, BasicType type, - LIR_PatchCode patch_code = lir_patch_none, - CodeEmitInfo* info = NULL, bool unaligned = false); + LIR_PatchCode patch_code, + CodeEmitInfo* info, bool wide, bool unaligned); void prefetchr (LIR_Opr src); void prefetchw (LIR_Opr src); @@ -211,7 +213,7 @@ class LIR_Assembler: public CompilationResourceObj { void roundfp_op(LIR_Opr src, LIR_Opr tmp, LIR_Opr dest, bool pop_fpu_stack); void move_op(LIR_Opr src, LIR_Opr result, BasicType type, - LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned); + LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned, bool wide); void volatile_move_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); void comp_mem_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); // info set for null exceptions void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op); diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 41bd2c5dd9f..b81d639f56d 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -864,11 +864,11 @@ void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) { // MDO cells are intptr_t, so the data_reg width is arch-dependent. LIR_Opr data_reg = new_pointer_register(); LIR_Address* data_addr = new LIR_Address(md_reg, data_offset_reg, data_reg->type()); - __ move(LIR_OprFact::address(data_addr), data_reg); + __ move(data_addr, data_reg); // Use leal instead of add to avoid destroying condition codes on x86 LIR_Address* fake_incr_value = new LIR_Address(data_reg, DataLayout::counter_increment, T_INT); __ leal(LIR_OprFact::address(fake_incr_value), data_reg); - __ move(data_reg, LIR_OprFact::address(data_addr)); + __ move(data_reg, data_addr); } } @@ -1009,12 +1009,12 @@ void LIRGenerator::do_ExceptionObject(ExceptionObject* x) { operand_for_instruction(phi)); LIR_Opr thread_reg = getThreadPointer(); - __ move(new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT), - exceptionOopOpr()); - __ move(LIR_OprFact::oopConst(NULL), - new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT)); - __ move(LIR_OprFact::oopConst(NULL), - new LIR_Address(thread_reg, in_bytes(JavaThread::exception_pc_offset()), T_OBJECT)); + __ move_wide(new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT), + exceptionOopOpr()); + __ move_wide(LIR_OprFact::oopConst(NULL), + new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT)); + __ move_wide(LIR_OprFact::oopConst(NULL), + new LIR_Address(thread_reg, in_bytes(JavaThread::exception_pc_offset()), T_OBJECT)); LIR_Opr result = new_register(T_OBJECT); __ move(exceptionOopOpr(), result); @@ -1085,7 +1085,7 @@ void LIRGenerator::do_IfInstanceOf(IfInstanceOf* x) { void LIRGenerator::do_Return(Return* x) { if (compilation()->env()->dtrace_method_probes()) { BasicTypeList signature; - signature.append(T_INT); // thread + signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread signature.append(T_OBJECT); // methodOop LIR_OprList* args = new LIR_OprList(); args->append(getThreadPointer()); @@ -1122,8 +1122,8 @@ void LIRGenerator::do_getClass(Intrinsic* x) { info = state_for(x); } __ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_OBJECT), result, info); - __ move(new LIR_Address(result, Klass::java_mirror_offset_in_bytes() + - klassOopDesc::klass_part_offset_in_bytes(), T_OBJECT), result); + __ move_wide(new LIR_Address(result, Klass::java_mirror_offset_in_bytes() + + klassOopDesc::klass_part_offset_in_bytes(), T_OBJECT), result); } @@ -1131,7 +1131,7 @@ void LIRGenerator::do_getClass(Intrinsic* x) { void LIRGenerator::do_currentThread(Intrinsic* x) { assert(x->number_of_arguments() == 0, "wrong type"); LIR_Opr reg = rlock_result(x); - __ load(new LIR_Address(getThreadPointer(), in_bytes(JavaThread::threadObj_offset()), T_OBJECT), reg); + __ move_wide(new LIR_Address(getThreadPointer(), in_bytes(JavaThread::threadObj_offset()), T_OBJECT), reg); } @@ -1908,7 +1908,11 @@ void LIRGenerator::do_UnsafeGetRaw(UnsafeGetRaw* x) { if (x->may_be_unaligned() && (dst_type == T_LONG || dst_type == T_DOUBLE)) { __ unaligned_move(addr, reg); } else { - __ move(addr, reg); + if (dst_type == T_OBJECT && x->is_wide()) { + __ move_wide(addr, reg); + } else { + __ move(addr, reg); + } } } @@ -2287,7 +2291,7 @@ void LIRGenerator::do_Base(Base* x) { if (compilation()->env()->dtrace_method_probes()) { BasicTypeList signature; - signature.append(T_INT); // thread + signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread signature.append(T_OBJECT); // methodOop LIR_OprList* args = new LIR_OprList(); args->append(getThreadPointer()); @@ -2352,11 +2356,14 @@ void LIRGenerator::invoke_load_arguments(Invoke* x, LIRItemList* args, const LIR } else { LIR_Address* addr = loc->as_address_ptr(); param->load_for_store(addr->type()); - if (addr->type() == T_LONG || addr->type() == T_DOUBLE) { - __ unaligned_move(param->result(), addr); - } else { - __ move(param->result(), addr); - } + if (addr->type() == T_OBJECT) { + __ move_wide(param->result(), addr); + } else + if (addr->type() == T_LONG || addr->type() == T_DOUBLE) { + __ unaligned_move(param->result(), addr); + } else { + __ move(param->result(), addr); + } } } @@ -2368,7 +2375,7 @@ void LIRGenerator::invoke_load_arguments(Invoke* x, LIRItemList* args, const LIR } else { assert(loc->is_address(), "just checking"); receiver->load_for_store(T_OBJECT); - __ move(receiver->result(), loc); + __ move_wide(receiver->result(), loc->as_address_ptr()); } } } diff --git a/hotspot/src/share/vm/c1/c1_LinearScan.cpp b/hotspot/src/share/vm/c1/c1_LinearScan.cpp index c77b3d19cc5..fe118944a02 100644 --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp @@ -1273,7 +1273,7 @@ void LinearScan::build_intervals() { int caller_save_registers[LinearScan::nof_regs]; int i; - for (i = 0; i < FrameMap::nof_caller_save_cpu_regs; i++) { + for (i = 0; i < FrameMap::nof_caller_save_cpu_regs(); i++) { LIR_Opr opr = FrameMap::caller_save_cpu_reg_at(i); assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands"); assert(reg_numHi(opr) == -1, "missing addition of range for hi-register"); @@ -3557,7 +3557,7 @@ void RegisterVerifier::process_operations(LIR_List* ops, IntervalList* input_sta // invalidate all caller save registers at calls if (visitor.has_call()) { - for (j = 0; j < FrameMap::nof_caller_save_cpu_regs; j++) { + for (j = 0; j < FrameMap::nof_caller_save_cpu_regs(); j++) { state_put(input_state, reg_num(FrameMap::caller_save_cpu_reg_at(j)), NULL); } for (j = 0; j < FrameMap::nof_caller_save_fpu_regs; j++) { @@ -5596,7 +5596,7 @@ void LinearScanWalker::init_vars_for_alloc(Interval* cur) { _last_reg = pd_last_fpu_reg; } else { _first_reg = pd_first_cpu_reg; - _last_reg = pd_last_cpu_reg; + _last_reg = FrameMap::last_cpu_reg(); } assert(0 <= _first_reg && _first_reg < LinearScan::nof_regs, "out of range"); diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index fe754ab78fc..89cb28c38af 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -1174,7 +1174,7 @@ JRT_LEAF(int, Runtime1::arraycopy(oopDesc* src, int src_pos, oopDesc* dst, int d memmove(dst_addr, src_addr, length << l2es); return ac_ok; } else if (src->is_objArray() && dst->is_objArray()) { - if (UseCompressedOops) { // will need for tiered + if (UseCompressedOops) { narrowOop *src_addr = objArrayOop(src)->obj_at_addr(src_pos); narrowOop *dst_addr = objArrayOop(dst)->obj_at_addr(dst_pos); return obj_arraycopy_work(src, src_addr, dst, dst_addr, length); @@ -1210,10 +1210,11 @@ JRT_LEAF(void, Runtime1::oop_arraycopy(HeapWord* src, HeapWord* dst, int num)) assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well."); if (UseCompressedOops) { bs->write_ref_array_pre((narrowOop*)dst, num); + Copy::conjoint_oops_atomic((narrowOop*) src, (narrowOop*) dst, num); } else { bs->write_ref_array_pre((oop*)dst, num); + Copy::conjoint_oops_atomic((oop*) src, (oop*) dst, num); } - Copy::conjoint_oops_atomic((oop*) src, (oop*) dst, num); bs->write_ref_array(dst, num); JRT_END diff --git a/hotspot/src/share/vm/code/relocInfo.cpp b/hotspot/src/share/vm/code/relocInfo.cpp index a397546d442..fa63dc7d827 100644 --- a/hotspot/src/share/vm/code/relocInfo.cpp +++ b/hotspot/src/share/vm/code/relocInfo.cpp @@ -1093,8 +1093,8 @@ void RelocIterator::print_current() { tty->print_cr("(no relocs)"); return; } - tty->print("relocInfo@" INTPTR_FORMAT " [type=%d(%s) addr=" INTPTR_FORMAT, - _current, type(), reloc_type_string((relocInfo::relocType) type()), _addr); + tty->print("relocInfo@" INTPTR_FORMAT " [type=%d(%s) addr=" INTPTR_FORMAT " offset=%d", + _current, type(), reloc_type_string((relocInfo::relocType) type()), _addr, _current->addr_offset()); if (current()->format() != 0) tty->print(" format=%d", current()->format()); if (datalen() == 1) { diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index f9cf604d629..0a3f9207f0a 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1007,24 +1007,9 @@ static void no_shared_spaces() { void Arguments::check_compressed_oops_compat() { #ifdef _LP64 assert(UseCompressedOops, "Precondition"); -# if defined(COMPILER1) && !defined(TIERED) - // Until c1 supports compressed oops turn them off. - FLAG_SET_DEFAULT(UseCompressedOops, false); -# else // Is it on by default or set on ergonomically bool is_on_by_default = FLAG_IS_DEFAULT(UseCompressedOops) || FLAG_IS_ERGO(UseCompressedOops); - // Tiered currently doesn't work with compressed oops - if (TieredCompilation) { - if (is_on_by_default) { - FLAG_SET_DEFAULT(UseCompressedOops, false); - return; - } else { - vm_exit_during_initialization( - "Tiered compilation is not supported with compressed oops yet", NULL); - } - } - // If dumping an archive or forcing its use, disable compressed oops if possible if (DumpSharedSpaces || RequireSharedSpaces) { if (is_on_by_default) { @@ -1038,9 +1023,7 @@ void Arguments::check_compressed_oops_compat() { // UseSharedSpaces is on by default. With compressed oops, we turn it off. FLAG_SET_DEFAULT(UseSharedSpaces, false); } - -# endif // defined(COMPILER1) && !defined(TIERED) -#endif // _LP64 +#endif } void Arguments::set_tiered_flags() { @@ -3075,11 +3058,9 @@ jint Arguments::parse(const JavaVMInitArgs* args) { // Set flags based on ergonomics. set_ergonomics_flags(); -#ifdef _LP64 if (UseCompressedOops) { check_compressed_oops_compat(); } -#endif // Check the GC selections again. if (!check_gc_consistency()) { From 92db57255dadc92cae7fe1ec239f3520d12fac0d Mon Sep 17 00:00:00 2001 From: Andrei Dmitriev Date: Wed, 1 Dec 2010 14:43:56 +0300 Subject: [PATCH 016/139] 6709453: (dav)Screen flickers when a JFrame switches to fullscreen mode Reviewed-by: art, dcherepanov --- .../windows/classes/sun/awt/Win32GraphicsDevice.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/jdk/src/windows/classes/sun/awt/Win32GraphicsDevice.java b/jdk/src/windows/classes/sun/awt/Win32GraphicsDevice.java index 5663a9ff7f3..14b93bd0e2b 100644 --- a/jdk/src/windows/classes/sun/awt/Win32GraphicsDevice.java +++ b/jdk/src/windows/classes/sun/awt/Win32GraphicsDevice.java @@ -30,6 +30,7 @@ import java.awt.GraphicsDevice; import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; import java.awt.DisplayMode; +import java.awt.EventQueue; import java.awt.Frame; import java.awt.Rectangle; import java.awt.Window; @@ -610,11 +611,18 @@ public class Win32GraphicsDevice extends GraphicsDevice implements * * @param w full-screen window */ - protected void addFSWindowListener(Window w) { + protected void addFSWindowListener(final Window w) { // Note: even though we create a listener for Window instances of // fs windows they will not receive window events. fsWindowListener = new Win32FSWindowAdapter(this); - w.addWindowListener(fsWindowListener); + + // Fix for 6709453. Using invokeLater to avoid listening + // for the events already posted to the queue. + EventQueue.invokeLater(new Runnable() { + public void run() { + w.addWindowListener(fsWindowListener); + } + }); } /** From 3111dfa081ad8f8dbc1ae4ec33058a0eb3cb3e0b Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Wed, 1 Dec 2010 13:49:02 +0000 Subject: [PATCH 017/139] 6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win] Reviewed-by: chegar --- .../classes/java/io/FileOutputStream.java | 41 +++++-- .../classes/java/lang/ProcessBuilder.java | 14 +-- .../classes/sun/nio/ch/FileChannelImpl.java | 28 +++-- .../share/native/java/io/RandomAccessFile.c | 4 +- jdk/src/share/native/java/io/io_util.c | 16 ++- jdk/src/share/native/java/io/io_util.h | 4 +- .../classes/java/lang/ProcessImpl.java | 6 +- .../sun/nio/ch/FileDispatcherImpl.java | 7 ++ .../native/java/io/FileOutputStream_md.c | 8 +- jdk/src/solaris/native/java/io/io_util_md.h | 3 +- .../classes/java/lang/ProcessImpl.java | 47 +++++++- .../sun/nio/ch/FileDispatcherImpl.java | 22 +++- .../sun/nio/fs/WindowsChannelFactory.java | 4 +- .../native/java/io/FileOutputStream_md.c | 9 +- jdk/src/windows/native/java/io/io_util_md.c | 43 ++++--- jdk/src/windows/native/java/io/io_util_md.h | 4 +- .../windows/native/java/lang/ProcessImpl_md.c | 48 ++++++++ .../native/sun/nio/ch/FileDispatcherImpl.c | 32 +++++- .../channels/FileChannel/AtomicAppend.java | 107 ++++++++++++++++++ .../java/nio/channels/FileChannel/Lock.java | 23 +++- .../nio/channels/FileChannel/Truncate.java | 92 ++++++++++----- 21 files changed, 457 insertions(+), 105 deletions(-) create mode 100644 jdk/test/java/nio/channels/FileChannel/AtomicAppend.java diff --git a/jdk/src/share/classes/java/io/FileOutputStream.java b/jdk/src/share/classes/java/io/FileOutputStream.java index 71bdee89f3b..70f6851d732 100644 --- a/jdk/src/share/classes/java/io/FileOutputStream.java +++ b/jdk/src/share/classes/java/io/FileOutputStream.java @@ -56,7 +56,15 @@ class FileOutputStream extends OutputStream */ private final FileDescriptor fd; - private FileChannel channel= null; + /** + * True if the file is opened for append. + */ + private final boolean append; + + /** + * The associated channel, initalized lazily. + */ + private FileChannel channel; private final Object closeLock = new Object(); private volatile boolean closed = false; @@ -196,7 +204,9 @@ class FileOutputStream extends OutputStream if (name == null) { throw new NullPointerException(); } - fd = new FileDescriptor(); + this.fd = new FileDescriptor(); + this.append = append; + fd.incrementAndGetUseCount(); open(name, append); } @@ -232,7 +242,8 @@ class FileOutputStream extends OutputStream if (security != null) { security.checkWrite(fdObj); } - fd = fdObj; + this.fd = fdObj; + this.append = false; /* * FileDescriptor is being shared by streams. @@ -250,6 +261,15 @@ class FileOutputStream extends OutputStream private native void open(String name, boolean append) throws FileNotFoundException; + /** + * Writes the specified byte to this file output stream. + * + * @param b the byte to be written. + * @param append {@code true} if the write operation first + * advances the position to the end of file + */ + private native void write(int b, boolean append) throws IOException; + /** * Writes the specified byte to this file output stream. Implements * the write method of OutputStream. @@ -257,16 +277,21 @@ class FileOutputStream extends OutputStream * @param b the byte to be written. * @exception IOException if an I/O error occurs. */ - public native void write(int b) throws IOException; + public void write(int b) throws IOException { + write(b, append); + } /** * Writes a sub array as a sequence of bytes. * @param b the data to be written * @param off the start offset in the data * @param len the number of bytes that are written + * @param append {@code true} to first advance the position to the + * end of file * @exception IOException If an I/O error has occurred. */ - private native void writeBytes(byte b[], int off, int len) throws IOException; + private native void writeBytes(byte b[], int off, int len, boolean append) + throws IOException; /** * Writes b.length bytes from the specified byte array @@ -276,7 +301,7 @@ class FileOutputStream extends OutputStream * @exception IOException if an I/O error occurs. */ public void write(byte b[]) throws IOException { - writeBytes(b, 0, b.length); + writeBytes(b, 0, b.length, append); } /** @@ -289,7 +314,7 @@ class FileOutputStream extends OutputStream * @exception IOException if an I/O error occurs. */ public void write(byte b[], int off, int len) throws IOException { - writeBytes(b, off, len); + writeBytes(b, off, len, append); } /** @@ -372,7 +397,7 @@ class FileOutputStream extends OutputStream public FileChannel getChannel() { synchronized (this) { if (channel == null) { - channel = FileChannelImpl.open(fd, false, true, this); + channel = FileChannelImpl.open(fd, false, true, append, this); /* * Increment fd's use count. Invoking the channel's close() diff --git a/jdk/src/share/classes/java/lang/ProcessBuilder.java b/jdk/src/share/classes/java/lang/ProcessBuilder.java index 97ce45cdf65..ebc372380bb 100644 --- a/jdk/src/share/classes/java/lang/ProcessBuilder.java +++ b/jdk/src/share/classes/java/lang/ProcessBuilder.java @@ -537,7 +537,11 @@ public final class ProcessBuilder */ public File file() { return null; } - FileOutputStream toFileOutputStream() throws IOException { + /** + * When redirected to a destination file, indicates if the output + * is to be written to the end of the file. + */ + boolean append() { throw new UnsupportedOperationException(); } @@ -588,9 +592,7 @@ public final class ProcessBuilder public String toString() { return "redirect to write to file \"" + file + "\""; } - FileOutputStream toFileOutputStream() throws IOException { - return new FileOutputStream(file, false); - } + boolean append() { return false; } }; } @@ -620,9 +622,7 @@ public final class ProcessBuilder public String toString() { return "redirect to append to file \"" + file + "\""; } - FileOutputStream toFileOutputStream() throws IOException { - return new FileOutputStream(file, true); - } + boolean append() { return true; } }; } diff --git a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java index e37fe799d84..32d0be649d3 100644 --- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java @@ -39,13 +39,12 @@ import sun.security.action.GetPropertyAction; public class FileChannelImpl extends FileChannel { - - // Used to make native read and write calls - private static final FileDispatcher nd; - // Memory allocation size for mapping buffers private static final long allocationGranularity; + // Used to make native read and write calls + private final FileDispatcher nd; + // File descriptor private final FileDescriptor fd; @@ -63,22 +62,29 @@ public class FileChannelImpl private final Object positionLock = new Object(); private FileChannelImpl(FileDescriptor fd, boolean readable, - boolean writable, Object parent) + boolean writable, boolean append, Object parent) { this.fd = fd; this.readable = readable; this.writable = writable; this.parent = parent; + this.nd = new FileDispatcherImpl(append); } - // Invoked by getChannel() methods - // of java.io.File{Input,Output}Stream and RandomAccessFile - // + // Used by FileInputStream.getChannel() and RandomAccessFile.getChannel() public static FileChannel open(FileDescriptor fd, boolean readable, boolean writable, Object parent) { - return new FileChannelImpl(fd, readable, writable, parent); + return new FileChannelImpl(fd, readable, writable, false, parent); + } + + // Used by FileOutputStream.getChannel + public static FileChannel open(FileDescriptor fd, + boolean readable, boolean writable, + boolean append, Object parent) + { + return new FileChannelImpl(fd, readable, writable, append, parent); } private void ensureOpen() throws IOException { @@ -704,6 +710,9 @@ public class FileChannelImpl private static class Unmapper implements Runnable { + // may be required to close file + private static final NativeDispatcher nd = new FileDispatcherImpl(); + // keep track of mapped buffer usage static volatile int count; static volatile long totalSize; @@ -1119,7 +1128,6 @@ public class FileChannelImpl static { Util.load(); allocationGranularity = initIDs(); - nd = new FileDispatcherImpl(); } } diff --git a/jdk/src/share/native/java/io/RandomAccessFile.c b/jdk/src/share/native/java/io/RandomAccessFile.c index a8c3390b677..437bab6b831 100644 --- a/jdk/src/share/native/java/io/RandomAccessFile.c +++ b/jdk/src/share/native/java/io/RandomAccessFile.c @@ -76,13 +76,13 @@ Java_java_io_RandomAccessFile_readBytes(JNIEnv *env, JNIEXPORT void JNICALL Java_java_io_RandomAccessFile_write(JNIEnv *env, jobject this, jint byte) { - writeSingle(env, this, byte, raf_fd); + writeSingle(env, this, byte, JNI_FALSE, raf_fd); } JNIEXPORT void JNICALL Java_java_io_RandomAccessFile_writeBytes(JNIEnv *env, jobject this, jbyteArray bytes, jint off, jint len) { - writeBytes(env, this, bytes, off, len, raf_fd); + writeBytes(env, this, bytes, off, len, JNI_FALSE, raf_fd); } JNIEXPORT jlong JNICALL diff --git a/jdk/src/share/native/java/io/io_util.c b/jdk/src/share/native/java/io/io_util.c index 986416e20d8..cef7d272ba2 100644 --- a/jdk/src/share/native/java/io/io_util.c +++ b/jdk/src/share/native/java/io/io_util.c @@ -127,7 +127,7 @@ readBytes(JNIEnv *env, jobject this, jbyteArray bytes, } void -writeSingle(JNIEnv *env, jobject this, jint byte, jfieldID fid) { +writeSingle(JNIEnv *env, jobject this, jint byte, jboolean append, jfieldID fid) { // Discard the 24 high-order bits of byte. See OutputStream#write(int) char c = (char) byte; jint n; @@ -136,7 +136,11 @@ writeSingle(JNIEnv *env, jobject this, jint byte, jfieldID fid) { JNU_ThrowIOException(env, "Stream Closed"); return; } - n = IO_Write(fd, &c, 1); + if (append == JNI_TRUE) { + n = IO_Append(fd, &c, 1); + } else { + n = IO_Write(fd, &c, 1); + } if (n == JVM_IO_ERR) { JNU_ThrowIOExceptionWithLastError(env, "Write error"); } else if (n == JVM_IO_INTR) { @@ -146,7 +150,7 @@ writeSingle(JNIEnv *env, jobject this, jint byte, jfieldID fid) { void writeBytes(JNIEnv *env, jobject this, jbyteArray bytes, - jint off, jint len, jfieldID fid) + jint off, jint len, jboolean append, jfieldID fid) { jint n; char stackBuf[BUF_SIZE]; @@ -185,7 +189,11 @@ writeBytes(JNIEnv *env, jobject this, jbyteArray bytes, JNU_ThrowIOException(env, "Stream Closed"); break; } - n = IO_Write(fd, buf+off, len); + if (append == JNI_TRUE) { + n = IO_Append(fd, buf+off, len); + } else { + n = IO_Write(fd, buf+off, len); + } if (n == JVM_IO_ERR) { JNU_ThrowIOExceptionWithLastError(env, "Write error"); break; diff --git a/jdk/src/share/native/java/io/io_util.h b/jdk/src/share/native/java/io/io_util.h index 436acdff16d..b98c5274a48 100644 --- a/jdk/src/share/native/java/io/io_util.h +++ b/jdk/src/share/native/java/io/io_util.h @@ -41,9 +41,9 @@ extern jfieldID IO_handle_fdID; jint readSingle(JNIEnv *env, jobject this, jfieldID fid); jint readBytes(JNIEnv *env, jobject this, jbyteArray bytes, jint off, jint len, jfieldID fid); -void writeSingle(JNIEnv *env, jobject this, jint byte, jfieldID fid); +void writeSingle(JNIEnv *env, jobject this, jint byte, jboolean append, jfieldID fid); void writeBytes(JNIEnv *env, jobject this, jbyteArray bytes, jint off, - jint len, jfieldID fid); + jint len, jboolean append, jfieldID fid); void fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags); void throwFileNotFoundException(JNIEnv *env, jstring path); diff --git a/jdk/src/solaris/classes/java/lang/ProcessImpl.java b/jdk/src/solaris/classes/java/lang/ProcessImpl.java index 5c291b138c3..ed0c6397677 100644 --- a/jdk/src/solaris/classes/java/lang/ProcessImpl.java +++ b/jdk/src/solaris/classes/java/lang/ProcessImpl.java @@ -111,7 +111,8 @@ final class ProcessImpl { else if (redirects[1] == Redirect.INHERIT) std_fds[1] = 1; else { - f1 = redirects[1].toFileOutputStream(); + f1 = new FileOutputStream(redirects[1].file(), + redirects[1].append()); std_fds[1] = fdAccess.get(f1.getFD()); } @@ -120,7 +121,8 @@ final class ProcessImpl { else if (redirects[2] == Redirect.INHERIT) std_fds[2] = 2; else { - f2 = redirects[2].toFileOutputStream(); + f2 = new FileOutputStream(redirects[2].file(), + redirects[2].append()); std_fds[2] = fdAccess.get(f2.getFD()); } } diff --git a/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java b/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java index 6f17340372e..f56d317cc91 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java +++ b/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java @@ -35,6 +35,13 @@ class FileDispatcherImpl extends FileDispatcher init(); } + FileDispatcherImpl(boolean append) { + /* append is ignored */ + } + + FileDispatcherImpl() { + } + int read(FileDescriptor fd, long address, int len) throws IOException { return read0(fd, address, len); } diff --git a/jdk/src/solaris/native/java/io/FileOutputStream_md.c b/jdk/src/solaris/native/java/io/FileOutputStream_md.c index 1d71052ec56..ffc2011797d 100644 --- a/jdk/src/solaris/native/java/io/FileOutputStream_md.c +++ b/jdk/src/solaris/native/java/io/FileOutputStream_md.c @@ -60,14 +60,14 @@ Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, } JNIEXPORT void JNICALL -Java_java_io_FileOutputStream_write(JNIEnv *env, jobject this, jint byte) { - writeSingle(env, this, byte, fos_fd); +Java_java_io_FileOutputStream_write(JNIEnv *env, jobject this, jint byte, jboolean append) { + writeSingle(env, this, byte, append, fos_fd); } JNIEXPORT void JNICALL Java_java_io_FileOutputStream_writeBytes(JNIEnv *env, - jobject this, jbyteArray bytes, jint off, jint len) { - writeBytes(env, this, bytes, off, len, fos_fd); + jobject this, jbyteArray bytes, jint off, jint len, jboolean append) { + writeBytes(env, this, bytes, off, len, append, fos_fd); } JNIEXPORT void JNICALL diff --git a/jdk/src/solaris/native/java/io/io_util_md.h b/jdk/src/solaris/native/java/io/io_util_md.h index 378fbcb1ebc..b5fe90e6a73 100644 --- a/jdk/src/solaris/native/java/io/io_util_md.h +++ b/jdk/src/solaris/native/java/io/io_util_md.h @@ -53,8 +53,9 @@ #define THIS_FD(obj) (*env)->GetIntField(env, obj, IO_fd_fdID) /* - * Route the routines through HPI + * Route the routines through VM */ +#define IO_Append JVM_Write #define IO_Write JVM_Write #define IO_Sync JVM_Sync #define IO_Read JVM_Read diff --git a/jdk/src/windows/classes/java/lang/ProcessImpl.java b/jdk/src/windows/classes/java/lang/ProcessImpl.java index c0a0daa09a8..b3357dd0c9d 100644 --- a/jdk/src/windows/classes/java/lang/ProcessImpl.java +++ b/jdk/src/windows/classes/java/lang/ProcessImpl.java @@ -35,6 +35,8 @@ import java.io.FileDescriptor; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.lang.ProcessBuilder.Redirect; +import java.security.AccessController; +import java.security.PrivilegedAction; /* This class is for the exclusive use of ProcessBuilder.start() to * create new processes. @@ -47,6 +49,35 @@ final class ProcessImpl extends Process { private static final sun.misc.JavaIOFileDescriptorAccess fdAccess = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); + /** + * Open a file for writing. If {@code append} is {@code true} then the file + * is opened for atomic append directly and a FileOutputStream constructed + * with the resulting handle. This is because a FileOutputStream created + * to append to a file does not open the file in a manner that guarantees + * that writes by the child process will be atomic. + */ + private static FileOutputStream newFileOutputStream(File f, boolean append) + throws IOException + { + if (append) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkWrite(f.getPath()); + long handle = openForAtomicAppend(f.getPath()); + final FileDescriptor fd = new FileDescriptor(); + fdAccess.setHandle(fd, handle); + return AccessController.doPrivileged( + new PrivilegedAction() { + public FileOutputStream run() { + return new FileOutputStream(fd); + } + } + ); + } else { + return new FileOutputStream(f); + } + } + // System-dependent portion of ProcessBuilder.start() static Process start(String cmdarray[], java.util.Map environment, @@ -82,7 +113,8 @@ final class ProcessImpl extends Process { else if (redirects[1] == Redirect.INHERIT) stdHandles[1] = fdAccess.getHandle(FileDescriptor.out); else { - f1 = redirects[1].toFileOutputStream(); + f1 = newFileOutputStream(redirects[1].file(), + redirects[1].append()); stdHandles[1] = fdAccess.getHandle(f1.getFD()); } @@ -91,7 +123,8 @@ final class ProcessImpl extends Process { else if (redirects[2] == Redirect.INHERIT) stdHandles[2] = fdAccess.getHandle(FileDescriptor.err); else { - f2 = redirects[2].toFileOutputStream(); + f2 = newFileOutputStream(redirects[2].file(), + redirects[2].append()); stdHandles[2] = fdAccess.getHandle(f2.getFD()); } } @@ -251,5 +284,15 @@ final class ProcessImpl extends Process { boolean redirectErrorStream) throws IOException; + /** + * Opens a file for atomic append. The file is created if it doesn't + * already exist. + * + * @param file the file to open or create + * @return the native HANDLE + */ + private static native long openForAtomicAppend(String path) + throws IOException; + private static native boolean closeHandle(long handle); } diff --git a/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java b/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java index 2cdc8f8fe9f..43f0745be40 100644 --- a/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java +++ b/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java @@ -35,6 +35,20 @@ class FileDispatcherImpl extends FileDispatcher Util.load(); } + /** + * Indicates if the dispatcher should first advance the file position + * to the end of file when writing. + */ + private final boolean append; + + FileDispatcherImpl(boolean append) { + this.append = append; + } + + FileDispatcherImpl() { + this(false); + } + int read(FileDescriptor fd, long address, int len) throws IOException { @@ -54,7 +68,7 @@ class FileDispatcherImpl extends FileDispatcher } int write(FileDescriptor fd, long address, int len) throws IOException { - return write0(fd, address, len); + return write0(fd, address, len, append); } int pwrite(FileDescriptor fd, long address, int len, @@ -66,7 +80,7 @@ class FileDispatcherImpl extends FileDispatcher } long writev(FileDescriptor fd, long address, int len) throws IOException { - return writev0(fd, address, len); + return writev0(fd, address, len, append); } int force(FileDescriptor fd, boolean metaData) throws IOException { @@ -116,13 +130,13 @@ class FileDispatcherImpl extends FileDispatcher static native long readv0(FileDescriptor fd, long address, int len) throws IOException; - static native int write0(FileDescriptor fd, long address, int len) + static native int write0(FileDescriptor fd, long address, int len, boolean append) throws IOException; static native int pwrite0(FileDescriptor fd, long address, int len, long position) throws IOException; - static native long writev0(FileDescriptor fd, long address, int len) + static native long writev0(FileDescriptor fd, long address, int len, boolean append) throws IOException; static native int force0(FileDescriptor fd, boolean metaData) diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java b/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java index 3795a6f40d2..736ea7b1ea0 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java @@ -157,7 +157,7 @@ class WindowsChannelFactory { throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); FileDescriptor fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor); - return FileChannelImpl.open(fdObj, flags.read, flags.write, null); + return FileChannelImpl.open(fdObj, flags.read, flags.write, flags.append, null); } /** @@ -230,7 +230,7 @@ class WindowsChannelFactory { if (flags.read) dwDesiredAccess |= GENERIC_READ; if (flags.write) - dwDesiredAccess |= (flags.append) ? FILE_APPEND_DATA : GENERIC_WRITE; + dwDesiredAccess |= GENERIC_WRITE; int dwShareMode = 0; if (flags.shareRead) diff --git a/jdk/src/windows/native/java/io/FileOutputStream_md.c b/jdk/src/windows/native/java/io/FileOutputStream_md.c index 221ba504f5f..23c754d4667 100644 --- a/jdk/src/windows/native/java/io/FileOutputStream_md.c +++ b/jdk/src/windows/native/java/io/FileOutputStream_md.c @@ -61,14 +61,15 @@ Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, } JNIEXPORT void JNICALL -Java_java_io_FileOutputStream_write(JNIEnv *env, jobject this, jint byte) { - writeSingle(env, this, byte, fos_fd); +Java_java_io_FileOutputStream_write(JNIEnv *env, jobject this, jint byte, jboolean append) { + writeSingle(env, this, byte, append, fos_fd); } JNIEXPORT void JNICALL Java_java_io_FileOutputStream_writeBytes(JNIEnv *env, - jobject this, jbyteArray bytes, jint off, jint len) { - writeBytes(env, this, bytes, off, len, fos_fd); + jobject this, jbyteArray bytes, jint off, jint len, jboolean append) +{ + writeBytes(env, this, bytes, off, len, append, fos_fd); } JNIEXPORT void JNICALL diff --git a/jdk/src/windows/native/java/io/io_util_md.c b/jdk/src/windows/native/java/io/io_util_md.c index 722913f775a..a81e39e9851 100644 --- a/jdk/src/windows/native/java/io/io_util_md.c +++ b/jdk/src/windows/native/java/io/io_util_md.c @@ -225,14 +225,7 @@ pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE) { jlong winFileHandleOpen(JNIEnv *env, jstring path, int flags) { - /* To implement O_APPEND, we use the strategy from - http://msdn2.microsoft.com/en-us/library/aa363858.aspx - "You can get atomic append by opening a file with - FILE_APPEND_DATA access and _without_ FILE_WRITE_DATA access. - If you do this then all writes will ignore the current file - pointer and be done at the end-of file." */ const DWORD access = - (flags & O_APPEND) ? (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA) : (flags & O_WRONLY) ? GENERIC_WRITE : (flags & O_RDWR) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ; @@ -511,24 +504,42 @@ handleRead(jlong fd, void *buf, jint len) return read; } -JNIEXPORT -size_t -handleWrite(jlong fd, const void *buf, jint len) +static size_t writeInternal(jlong fd, const void *buf, jint len, jboolean append) { BOOL result = 0; DWORD written = 0; HANDLE h = (HANDLE)fd; if (h != INVALID_HANDLE_VALUE) { - result = WriteFile(h, /* File handle to write */ - buf, /* pointers to the buffers */ - len, /* number of bytes to write */ - &written, /* receives number of bytes written */ - NULL); /* no overlapped struct */ + OVERLAPPED ov; + LPOVERLAPPED lpOv; + if (append == JNI_TRUE) { + ov.Offset = (DWORD)0xFFFFFFFF; + ov.OffsetHigh = (DWORD)0xFFFFFFFF; + ov.hEvent = NULL; + lpOv = &ov; + } else { + lpOv = NULL; + } + result = WriteFile(h, /* File handle to write */ + buf, /* pointers to the buffers */ + len, /* number of bytes to write */ + &written, /* receives number of bytes written */ + lpOv); /* overlapped struct */ } if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { return -1; } - return written; + return (size_t)written; +} + +JNIEXPORT +size_t handleWrite(jlong fd, const void *buf, jint len) { + return writeInternal(fd, buf, len, JNI_FALSE); +} + +JNIEXPORT +size_t handleAppend(jlong fd, const void *buf, jint len) { + return writeInternal(fd, buf, len, JNI_TRUE); } jint diff --git a/jdk/src/windows/native/java/io/io_util_md.h b/jdk/src/windows/native/java/io/io_util_md.h index 6b6b89b6397..97a68c2feba 100644 --- a/jdk/src/windows/native/java/io/io_util_md.h +++ b/jdk/src/windows/native/java/io/io_util_md.h @@ -41,6 +41,7 @@ JNIEXPORT int handleSync(jlong fd); int handleSetLength(jlong fd, jlong length); JNIEXPORT size_t handleRead(jlong fd, void *buf, jint len); JNIEXPORT size_t handleWrite(jlong fd, const void *buf, jint len); +JNIEXPORT size_t handleAppend(jlong fd, const void *buf, jint len); jint handleClose(JNIEnv *env, jobject this, jfieldID fid); jlong handleLseek(jlong fd, jlong offset, jint whence); @@ -74,8 +75,9 @@ jlong winFileHandleOpen(JNIEnv *env, jstring path, int flags); #define THIS_FD(obj) (*env)->GetLongField(env, obj, IO_handle_fdID) /* - * Route the routines away from HPI layer + * Route the routines away from VM */ +#define IO_Append handleAppend #define IO_Write handleWrite #define IO_Sync handleSync #define IO_Read handleRead diff --git a/jdk/src/windows/native/java/lang/ProcessImpl_md.c b/jdk/src/windows/native/java/lang/ProcessImpl_md.c index e5fe23e71ec..afc5e7d2529 100644 --- a/jdk/src/windows/native/java/lang/ProcessImpl_md.c +++ b/jdk/src/windows/native/java/lang/ProcessImpl_md.c @@ -315,3 +315,51 @@ Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle { return CloseHandle((HANDLE) handle); } + +/** + * Returns a copy of the Unicode characters of a string. Fow now this + * function doesn't handle long path names and other issues. + */ +static WCHAR* getPath(JNIEnv *env, jstring ps) { + WCHAR *pathbuf = NULL; + const jchar *chars = (*(env))->GetStringChars(env, ps, NULL); + if (chars != NULL) { + size_t pathlen = wcslen(chars); + pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); + if (pathbuf == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + } else { + wcscpy(pathbuf, chars); + } + (*env)->ReleaseStringChars(env, ps, chars); + } + return pathbuf; +} + +JNIEXPORT jlong JNICALL +Java_java_lang_ProcessImpl_openForAtomicAppend(JNIEnv *env, jclass ignored, jstring path) +{ + const DWORD access = (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA); + const DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; + const DWORD disposition = OPEN_ALWAYS; + const DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + HANDLE h; + WCHAR *pathbuf = getPath(env, path); + if (pathbuf == NULL) { + /* Exception already pending */ + return -1; + } + h = CreateFileW( + pathbuf, /* Wide char path name */ + access, /* Read and/or write permission */ + sharing, /* File sharing flags */ + NULL, /* Security attributes */ + disposition, /* creation disposition */ + flagsAndAttributes, /* flags and attributes */ + NULL); + free(pathbuf); + if (h == INVALID_HANDLE_VALUE) { + JNU_ThrowIOExceptionWithLastError(env, "CreateFileW"); + } + return ptr_to_jlong(h); +} diff --git a/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c b/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c index f4d0b17d63b..2a146c284fa 100644 --- a/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c +++ b/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c @@ -184,18 +184,28 @@ Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv *env, jclass clazz, jobject fdo JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz, jobject fdo, - jlong address, jint len) + jlong address, jint len, jboolean append) { BOOL result = 0; DWORD written = 0; HANDLE h = (HANDLE)(handleval(env, fdo)); if (h != INVALID_HANDLE_VALUE) { + OVERLAPPED ov; + LPOVERLAPPED lpOv; + if (append == JNI_TRUE) { + ov.Offset = (DWORD)0xFFFFFFFF; + ov.OffsetHigh = (DWORD)0xFFFFFFFF; + ov.hEvent = NULL; + lpOv = &ov; + } else { + lpOv = NULL; + } result = WriteFile(h, /* File handle to write */ (LPCVOID)address, /* pointers to the buffers */ len, /* number of bytes to write */ &written, /* receives number of bytes written */ - NULL); /* no overlapped struct */ + lpOv); /* overlapped struct */ } if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { @@ -207,7 +217,7 @@ Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz, jobject fdo JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz, jobject fdo, - jlong address, jint len) + jlong address, jint len, jboolean append) { BOOL result = 0; DWORD written = 0; @@ -219,7 +229,16 @@ Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz, jobject fd int i = 0; DWORD num = 0; struct iovec *iovecp = (struct iovec *)jlong_to_ptr(address); - + OVERLAPPED ov; + LPOVERLAPPED lpOv; + if (append == JNI_TRUE) { + ov.Offset = (DWORD)0xFFFFFFFF; + ov.OffsetHigh = (DWORD)0xFFFFFFFF; + ov.hEvent = NULL; + lpOv = &ov; + } else { + lpOv = NULL; + } for(i=0; i 0) { totalWritten += written; } @@ -444,9 +463,10 @@ Java_sun_nio_ch_FileDispatcherImpl_closeByHandle(JNIEnv *env, jclass clazz, } JNIEXPORT jlong JNICALL -Java_sun_nio_ch_FileDispatcherImpl_duplicateHandle(JNIEnv *env, jclass this, jlong hFile) +Java_sun_nio_ch_FileDispatcherImpl_duplicateHandle(JNIEnv *env, jclass this, jlong handle) { HANDLE hProcess = GetCurrentProcess(); + HANDLE hFile = jlong_to_ptr(handle); HANDLE hResult; BOOL res = DuplicateHandle(hProcess, hFile, hProcess, &hResult, 0, FALSE, DUPLICATE_SAME_ACCESS); diff --git a/jdk/test/java/nio/channels/FileChannel/AtomicAppend.java b/jdk/test/java/nio/channels/FileChannel/AtomicAppend.java new file mode 100644 index 00000000000..1420318d5d7 --- /dev/null +++ b/jdk/test/java/nio/channels/FileChannel/AtomicAppend.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Check that appends are atomic + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.util.Random; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import static java.nio.file.StandardOpenOption.*; + +public class AtomicAppend { + static final Random rand = new Random(); + + // Open file for appending, returning FileChannel + static FileChannel newFileChannel(File file) throws IOException { + if (rand.nextBoolean()) { + return new FileOutputStream(file, true).getChannel(); + } else { + return FileChannel.open(file.toPath(), APPEND); + } + } + + // Open file for append, returning OutputStream + static OutputStream newOutputStream(File file) throws IOException { + if (rand.nextBoolean()) { + return new FileOutputStream(file, true); + } else { + return file.toPath().newOutputStream(APPEND); + } + } + + // write a byte to the given channel + static void write(FileChannel fc, int b) throws IOException { + ByteBuffer buf = ByteBuffer.allocate(1); + buf.put((byte)b); + buf.flip(); + if (rand.nextBoolean()) { + ByteBuffer[] bufs = new ByteBuffer[1]; + bufs[0] = buf; + fc.write(bufs); + } else { + fc.write(buf); + } + } + + public static void main(String[] args) throws Throwable { + final int nThreads = 16; + final int writes = 1000; + final File file = File.createTempFile("foo", null); + try { + ExecutorService pool = Executors.newFixedThreadPool(nThreads); + for (int i = 0; i < nThreads; i++) + pool.execute(new Runnable() { public void run() { + try { + // randomly choose FileChannel or OutputStream + if (rand.nextBoolean()) { + try (FileChannel fc = newFileChannel(file)) { + for (int j=0; j newSize) { - if (c.position() != newSize) - throw new RuntimeException("Position greater than size"); - } else { - if (c.position() != position) - throw new RuntimeException("Truncate changed position"); + if (position > newSize) { + if (fc.position() != newSize) + throw new RuntimeException("Position greater than size"); + } else { + if (fc.position() != position) + throw new RuntimeException("Truncate changed position"); + }; + } + } + } + + /** + * Test behavior of truncate method when file is opened for append + */ + static void appendTest(File blah) throws Exception { + for (int i=0; i<10; i++) { + long testSize = generator.nextInt(1000) + 10; + initTestFile(blah, testSize); + FileChannel fc = (i < 5) ? + new FileOutputStream(blah, true).getChannel() : + FileChannel.open(blah.toPath(), APPEND); + try (fc) { + // truncate file + long newSize = generator.nextInt((int)testSize); + fc.truncate(newSize); + if (fc.size() != newSize) + throw new RuntimeException("Truncate failed"); + + // write one byte + ByteBuffer buf = ByteBuffer.allocate(1); + buf.put((byte)'x'); + buf.flip(); + fc.write(buf); + if (fc.size() != (newSize+1)) + throw new RuntimeException("Unexpected size"); } - - c.close(); - fis.close(); } - blah.delete(); } /** From fe02e1f7c15c85ccfd33fd6bdbfaa1d1bcdbb1a1 Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Wed, 1 Dec 2010 17:25:12 +0300 Subject: [PATCH 018/139] 6945178: SecurityException upon drag-and-drop A flag added to distinguish drop action handling. Reviewed-by: uta, art --- .../classes/sun/awt/dnd/SunDropTargetContextPeer.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java b/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java index db92e68ffd9..19c2206fe93 100644 --- a/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java +++ b/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java @@ -94,6 +94,11 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, protected int dropStatus = STATUS_NONE; protected boolean dropComplete = false; + // The flag is used to monitor whether the drop action is + // handled by a user. That allows to distinct during + // which operation getTransferData() method is invoked. + boolean dropInProcess = false; + /* * global lock */ @@ -220,7 +225,7 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, SecurityManager sm = System.getSecurityManager(); try { - if (!dropComplete && sm != null) { + if (!dropInProcess && sm != null) { sm.checkSystemClipboardAccess(); } } catch (Exception e) { @@ -526,6 +531,8 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, setCurrentJVMLocalSourceTransferable(null); } + dropInProcess = true; + try { ((DropTargetListener)dt).drop(new DropTargetDropEvent(dtc, hots, @@ -538,6 +545,7 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, } else if (dropComplete == false) { dropComplete(false); } + dropInProcess = false; } } else { rejectDrop(); From 532dec3797420b625496e16b071e3a23b50a8521 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 1 Dec 2010 10:16:31 -0800 Subject: [PATCH 019/139] 7002666: eclipse CDT projects crash with compressed oops Reviewed-by: kvn, twisti --- hotspot/src/share/vm/opto/memnode.cpp | 10 ++-- .../test/compiler/7002666/Test7002666.java | 57 +++++++++++++++++++ 2 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 hotspot/test/compiler/7002666/Test7002666.java diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index bbdcaa55125..e3880ea4e59 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -3599,10 +3599,12 @@ Node* InitializeNode::complete_stores(Node* rawctl, Node* rawmem, Node* rawptr, intptr_t size_limit = phase->find_intptr_t_con(size_in_bytes, max_jint); if (zeroes_done + BytesPerLong >= size_limit) { assert(allocation() != NULL, ""); - Node* klass_node = allocation()->in(AllocateNode::KlassNode); - ciKlass* k = phase->type(klass_node)->is_klassptr()->klass(); - if (zeroes_done == k->layout_helper()) - zeroes_done = size_limit; + if (allocation()->Opcode() == Op_Allocate) { + Node* klass_node = allocation()->in(AllocateNode::KlassNode); + ciKlass* k = phase->type(klass_node)->is_klassptr()->klass(); + if (zeroes_done == k->layout_helper()) + zeroes_done = size_limit; + } } if (zeroes_done < size_limit) { rawmem = ClearArrayNode::clear_memory(rawctl, rawmem, rawptr, diff --git a/hotspot/test/compiler/7002666/Test7002666.java b/hotspot/test/compiler/7002666/Test7002666.java new file mode 100644 index 00000000000..caca8d8dcfd --- /dev/null +++ b/hotspot/test/compiler/7002666/Test7002666.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7002666 + * @summary eclipse CDT projects crash with compressed oops + * + * @run main/othervm -Xbatch -XX:CompileOnly=Test7002666.test,java/lang/reflect/Array Test7002666 + * + * This will only reliably fail with a fastdebug build since it relies + * on seeing garbage in the heap to die. It could be made more + * reliable in product mode but that would require greatly increasing + * the runtime. + */ + +public class Test7002666 { + public static void main(String[] args) { + for (int i = 0; i < 25000; i++) { + Object[] a = test(Test7002666.class, new Test7002666()); + if (a[0] != null) { + // The element should be null but if it's not then + // we've hit the bug. This will most likely crash but + // at least throw an exception. + System.err.println(a[0]); + throw new InternalError(a[0].toString()); + + } + } + } + public static Object[] test(Class c, Object o) { + // allocate an array small enough to be trigger the bug + Object[] a = (Object[])java.lang.reflect.Array.newInstance(c, 1); + return a; + } +} From 275e77646dba39dd6906819404b5f8c331327f00 Mon Sep 17 00:00:00 2001 From: Bhavesh Patel Date: Wed, 1 Dec 2010 11:02:38 -0800 Subject: [PATCH 020/139] 6851834: Javadoc doclet needs a structured approach to generate the output HTML Reviewed-by: jjg --- .../html/AbstractExecutableMemberWriter.java | 189 ++-- .../formats/html/AbstractIndexWriter.java | 189 ++-- .../formats/html/AbstractMemberWriter.java | 605 +++++++---- .../html/AbstractPackageIndexWriter.java | 144 +-- .../formats/html/AbstractTreeWriter.java | 120 +-- .../formats/html/AllClassesFrameWriter.java | 86 +- ...nnotationTypeOptionalMemberWriterImpl.java | 71 +- ...nnotationTypeRequiredMemberWriterImpl.java | 242 ++--- .../html/AnnotationTypeWriterImpl.java | 379 ++++--- .../doclets/formats/html/ClassUseWriter.java | 406 +++---- .../doclets/formats/html/ClassWriterImpl.java | 621 ++++++----- .../html/ConstantsSummaryWriterImpl.java | 306 +++--- .../formats/html/ConstructorWriterImpl.java | 285 +++-- .../formats/html/DeprecatedListWriter.java | 132 ++- .../formats/html/EnumConstantWriterImpl.java | 263 ++--- .../doclets/formats/html/FieldWriterImpl.java | 333 +++--- .../formats/html/FrameOutputWriter.java | 117 ++- .../doclets/formats/html/HelpWriter.java | 343 +++--- .../doclets/formats/html/HtmlDoclet.java | 5 +- .../formats/html/HtmlDocletWriter.java | 990 ++++++++++++++++-- .../formats/html/HtmlSerialFieldWriter.java | 175 ++-- .../formats/html/HtmlSerialMethodWriter.java | 120 ++- .../doclets/formats/html/LinkFactoryImpl.java | 2 +- .../formats/html/MethodWriterImpl.java | 390 ++++--- .../formats/html/NestedClassWriterImpl.java | 250 ++--- .../formats/html/PackageFrameWriter.java | 159 ++- .../formats/html/PackageIndexFrameWriter.java | 155 ++- .../formats/html/PackageIndexWriter.java | 188 ++-- .../formats/html/PackageTreeWriter.java | 123 +-- .../formats/html/PackageUseWriter.java | 258 +++-- .../formats/html/PackageWriterImpl.java | 243 +++-- .../html/SerializedFormWriterImpl.java | 177 +++- .../formats/html/SingleIndexWriter.java | 45 +- .../html}/SourceToHTMLConverter.java | 205 ++-- .../formats/html/SplitIndexWriter.java | 84 +- .../formats/html/StylesheetWriter.java | 130 --- .../formats/html/SubWriterHolderWriter.java | 223 +++- .../formats/html/TagletWriterImpl.java | 69 +- .../doclets/formats/html/TreeWriter.java | 103 +- .../doclets/formats/html/markup/Comment.java | 90 ++ .../doclets/formats/html/markup/DocType.java | 113 ++ .../doclets/formats/html/markup/HtmlAttr.java | 73 ++ .../formats/html/markup/HtmlConstants.java | 189 ++++ .../formats/html/markup/HtmlDocWriter.java | 137 +-- .../formats/html/markup/HtmlDocument.java | 103 ++ .../formats/html/markup/HtmlStyle.java | 73 ++ .../doclets/formats/html/markup/HtmlTag.java | 126 +++ .../doclets/formats/html/markup/HtmlTree.java | 777 ++++++++++++++ .../formats/html/markup/HtmlWriter.java | 235 ++++- .../doclets/formats/html/markup/RawHtml.java | 88 ++ .../formats/html/markup/StringContent.java | 99 ++ .../html/resources/standard.properties | 11 +- .../AnnotationTypeOptionalMemberWriter.java | 10 +- .../AnnotationTypeRequiredMemberWriter.java | 64 +- .../toolkit/AnnotationTypeWriter.java | 111 +- .../doclets/internal/toolkit/ClassWriter.java | 202 ++-- .../toolkit/ConstantsSummaryWriter.java | 96 +- .../internal/toolkit/ConstructorWriter.java | 65 +- .../doclets/internal/toolkit/Content.java | 106 ++ .../internal/toolkit/EnumConstantWriter.java | 65 +- .../doclets/internal/toolkit/FieldWriter.java | 65 +- .../internal/toolkit/MemberSummaryWriter.java | 71 +- .../internal/toolkit/MethodWriter.java | 67 +- .../internal/toolkit/NestedClassWriter.java | 49 +- .../toolkit/PackageSummaryWriter.java | 68 +- .../toolkit/SerializedFormWriter.java | 203 +++- .../toolkit/builders/AbstractBuilder.java | 21 +- .../builders/AbstractMemberBuilder.java | 8 +- .../builders/AnnotationTypeBuilder.java | 170 +-- .../AnnotationTypeOptionalMemberBuilder.java | 32 +- .../AnnotationTypeRequiredMemberBuilder.java | 97 +- .../toolkit/builders/ClassBuilder.java | 322 +++--- .../builders/ConstantsSummaryBuilder.java | 134 ++- .../toolkit/builders/ConstructorBuilder.java | 343 +++--- .../toolkit/builders/EnumConstantBuilder.java | 349 +++--- .../toolkit/builders/FieldBuilder.java | 342 +++--- .../toolkit/builders/LayoutParser.java | 2 +- .../builders/MemberSummaryBuilder.java | 433 ++++---- .../toolkit/builders/MethodBuilder.java | 333 +++--- .../builders/PackageSummaryBuilder.java | 542 +++++----- .../builders/SerializedFormBuilder.java | 555 +++++----- .../internal/toolkit/resources/doclet.xml | 243 ++--- .../toolkit/resources/doclets.properties | 21 +- .../internal/toolkit/resources/stylesheet.css | 439 ++++++++ .../toolkit/util/DirectoryManager.java | 18 +- .../doclets/internal/toolkit/util/Util.java | 70 +- .../AccessAsciiArt/AccessAsciiArt.java | 6 +- .../com/sun/javadoc/AccessH1/AccessH1.java | 25 +- .../javadoc/AccessSkipNav/AccessSkipNav.java | 19 +- .../javadoc/AccessSummary/AccessSummary.java | 8 +- .../com/sun/javadoc/AuthorDD/AuthorDD.java | 4 +- .../JavascriptWinTitle.java | 36 +- .../test/com/sun/javadoc/MetaTag/MetaTag.java | 18 +- .../com/sun/javadoc/ValidHtml/ValidHtml.java | 126 ++- .../javadoc/VersionNumber/VersionNumber.java | 2 +- .../javadoc/WindowTitles/WindowTitles.java | 34 +- .../TestConstantValuesDriver.java | 2 +- .../TestClassCrossReferences.java | 18 +- .../javadoc/testClassTree/TestClassTree.java | 33 +- .../TestConstructorIndent.java | 8 +- .../TestDeprecatedDocs.java | 27 +- .../TestDocRootInlineTag.java | 8 +- .../TestExternalOverridenMethod.java | 20 +- .../javadoc/testHeadings/TestHeadings.java | 57 +- .../testHelpOption/TestHelpOption.java | 3 +- .../com/sun/javadoc/testHref/TestHref.java | 20 +- .../TestHtmlDefinitionListTag.java | 419 +++----- .../testHtmlDocument/TestHtmlDocument.java | 155 +++ .../javadoc/testHtmlDocument/testLink.html | 9 + .../javadoc/testHtmlDocument/testMarkup.html | 18 + .../testHtmlStrongTag/TestHtmlStrongTag.java | 2 +- .../testHtmlTableTags/TestHtmlTableTags.java | 377 +++---- .../sun/javadoc/testHtmlTag/TestHtmlTag.java | 18 +- .../com/sun/javadoc/testIndex/TestIndex.java | 41 +- .../TestInlineLinkLabel.java | 4 +- .../javadoc/testInterface/TestInterface.java | 51 +- .../testJavascript/TestJavascript.java | 8 +- .../testLinkOption/TestLinkOption.java | 24 +- .../testLinkTaglet/TestLinkTaglet.java | 22 +- .../TestLinkToSerialForm.java | 4 +- .../TestMemberInheritence.java | 34 +- .../testMemberSummary/TestMemberSummary.java | 18 +- .../testNavagation/TestNavagation.java | 20 +- .../TestNewLanguageFeatures.java | 674 ++++++------ .../TestMultiInheritence.java | 29 +- .../TestOverridenMethodDocCopy.java | 6 +- .../TestOverridenPrivateMethods.java | 17 +- ...verridenPrivateMethodsWithPackageFlag.java | 24 +- ...verridenPrivateMethodsWithPrivateFlag.java | 18 +- .../testPackagePage/TestPackagePage.java | 21 +- .../testParamTaglet/TestParamTaglet.java | 10 +- .../TestPrivateClasses.java | 133 +-- .../TestSerializedForm.java | 6 +- .../TestSerializedFormDeprecationInfo.java | 81 +- .../javadoc/testSimpleTag/TestSimpleTag.java | 8 +- .../testStylesheet/TestStylesheet.java | 34 +- .../TestSummaryHeading.java | 3 +- .../TestSuperClassInSerialForm.java | 2 +- .../TestTagInheritence.java | 4 +- .../sun/javadoc/testTaglets/TestTaglets.java | 6 +- .../sun/javadoc/testTaglets/taglets/Foo.java | 4 +- .../testThrowsHead/TestThrowsHead.java | 2 +- .../javadoc/testThrowsTag/TestThrowsTag.java | 16 +- .../testTitleInHref/TestTitleInHref.java | 6 +- .../testTypeParams/TestTypeParameters.java | 11 +- .../TestUnnamedPackage.java | 6 +- .../javadoc/testValueTag/TestValueTag.java | 36 +- .../javadoc/testWarnings/TestWarnings.java | 6 +- 148 files changed, 12175 insertions(+), 7441 deletions(-) rename langtools/src/share/classes/com/sun/tools/doclets/{internal/toolkit/util => formats/html}/SourceToHTMLConverter.java (56%) delete mode 100644 langtools/src/share/classes/com/sun/tools/doclets/formats/html/StylesheetWriter.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/Comment.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/DocType.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlAttr.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocument.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTag.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/RawHtml.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/StringContent.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Content.java create mode 100644 langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css create mode 100644 langtools/test/com/sun/javadoc/testHtmlDocument/TestHtmlDocument.java create mode 100644 langtools/test/com/sun/javadoc/testHtmlDocument/testLink.html create mode 100644 langtools/test/com/sun/javadoc/testHtmlDocument/testMarkup.html diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java index f7e87b9c996..aae7eb17d33 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java @@ -26,12 +26,16 @@ package com.sun.tools.doclets.formats.html; import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.internal.toolkit.util.*; /** * Print method and constructor info. * * @author Robert Field * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWriter { @@ -45,82 +49,111 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite } /** - * Write the type parameters for the executable member. + * Add the type parameters for the executable member. * * @param member the member to write type parameters for. + * @param htmltree the content tree to which the parameters will be added. * @return the display length required to write this information. */ - protected int writeTypeParameters(ExecutableMemberDoc member) { + protected int addTypeParameters(ExecutableMemberDoc member, Content htmltree) { LinkInfoImpl linkInfo = new LinkInfoImpl( LinkInfoImpl.CONTEXT_MEMBER_TYPE_PARAMS, member, false); String typeParameters = writer.getTypeParameterLinks(linkInfo); if (linkInfo.displayLength > 0) { - writer.print(typeParameters + " "); + Content linkContent = new RawHtml(typeParameters); + htmltree.addContent(linkContent); + htmltree.addContent(writer.getSpace()); writer.displayLength += linkInfo.displayLength + 1; } return linkInfo.displayLength; } - protected void writeSignature(ExecutableMemberDoc member) { - writer.displayLength = 0; - writer.pre(); - writer.writeAnnotationInfo(member); - printModifiers(member); - writeTypeParameters(member); - if (configuration().linksource && - member.position().line() != classdoc.position().line()) { - writer.printSrcLink(member, member.name()); - } else { - strong(member.name()); - } - writeParameters(member); - writeExceptions(member); - writer.preEnd(); - } - - protected void writeDeprecatedLink(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + protected Content getDeprecatedLink(ProgramElementDoc member) { ExecutableMemberDoc emd = (ExecutableMemberDoc)member; - writer.printDocLink(LinkInfoImpl.CONTEXT_MEMBER, (MemberDoc) emd, - emd.qualifiedName() + emd.flatSignature(), false); + return writer.getDocLink(LinkInfoImpl.CONTEXT_MEMBER, (MemberDoc) emd, + emd.qualifiedName() + emd.flatSignature()); } - protected void writeSummaryLink(int context, ClassDoc cd, ProgramElementDoc member) { + /** + * Add the summary link for the member. + * + * @param context the id of the context where the link will be printed + * @param classDoc the classDoc that we should link to + * @param member the member being linked to + * @param tdSummary the content tree to which the link will be added + */ + protected void addSummaryLink(int context, ClassDoc cd, ProgramElementDoc member, + Content tdSummary) { ExecutableMemberDoc emd = (ExecutableMemberDoc)member; String name = emd.name(); - writer.strong(); - writer.printDocLink(context, cd, (MemberDoc) emd, - name, false); - writer.strongEnd(); + Content strong = HtmlTree.STRONG(new RawHtml( + writer.getDocLink(context, cd, (MemberDoc) emd, + name, false))); + Content code = HtmlTree.CODE(strong); writer.displayLength = name.length(); - writeParameters(emd, false); + addParameters(emd, false, code); + tdSummary.addContent(code); } - protected void writeInheritedSummaryLink(ClassDoc cd, - ProgramElementDoc member) { - writer.printDocLink(LinkInfoImpl.CONTEXT_MEMBER, cd, (MemberDoc) member, - member.name(), false); + /** + * Add the inherited summary link for the member. + * + * @param classDoc the classDoc that we should link to + * @param member the member being linked to + * @param linksTree the content tree to which the link will be added + */ + protected void addInheritedSummaryLink(ClassDoc cd, + ProgramElementDoc member, Content linksTree) { + linksTree.addContent(new RawHtml( + writer.getDocLink(LinkInfoImpl.CONTEXT_MEMBER, cd, (MemberDoc) member, + member.name(), false))); } - protected void writeParam(ExecutableMemberDoc member, Parameter param, - boolean isVarArg) { + /** + * Add the parameter for the executable member. + * + * @param member the member to write parameter for. + * @param param the parameter that needs to be written. + * @param isVarArg true if this is a link to var arg. + * @param tree the content tree to which the parameter information will be added. + */ + protected void addParam(ExecutableMemberDoc member, Parameter param, + boolean isVarArg, Content tree) { if (param.type() != null) { - writer.printLink(new LinkInfoImpl( - LinkInfoImpl.CONTEXT_EXECUTABLE_MEMBER_PARAM, param.type(), - isVarArg)); + Content link = new RawHtml(writer.getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_EXECUTABLE_MEMBER_PARAM, param.type(), + isVarArg))); + tree.addContent(link); } if(param.name().length() > 0) { - writer.space(); - writer.print(param.name()); + tree.addContent(writer.getSpace()); + tree.addContent(param.name()); } } - protected void writeParameters(ExecutableMemberDoc member) { - writeParameters(member, true); + /** + * Add all the parameters for the executable member. + * + * @param member the member to write parameters for. + * @param tree the content tree to which the parameters information will be added. + */ + protected void addParameters(ExecutableMemberDoc member, Content htmltree) { + addParameters(member, true, htmltree); } - protected void writeParameters(ExecutableMemberDoc member, - boolean includeAnnotations) { - print('('); + /** + * Add all the parameters for the executable member. + * + * @param member the member to write parameters for. + * @param includeAnnotations true if annotation information needs to be added. + * @param tree the content tree to which the parameters information will be added. + */ + protected void addParameters(ExecutableMemberDoc member, + boolean includeAnnotations, Content htmltree) { + htmltree.addContent("("); Parameter[] params = member.parameters(); String indent = makeSpace(writer.displayLength); if (configuration().linksource) { @@ -132,58 +165,70 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite Parameter param = params[paramstart]; if (!param.name().startsWith("this$")) { if (includeAnnotations) { - boolean foundAnnotations = - writer.writeAnnotationInfo(indent.length(), member, param); - if (foundAnnotations) { - writer.println(); - writer.print(indent); + boolean foundAnnotations = + writer.addAnnotationInfo(indent.length(), + member, param, htmltree); + if (foundAnnotations) { + htmltree.addContent(DocletConstants.NL); + htmltree.addContent(indent); } } - writeParam(member, param, - (paramstart == params.length - 1) && member.isVarArgs()); + addParam(member, param, + (paramstart == params.length - 1) && member.isVarArgs(), htmltree); break; } } for (int i = paramstart + 1; i < params.length; i++) { - writer.print(','); - writer.println(); - writer.print(indent); + htmltree.addContent(","); + htmltree.addContent(DocletConstants.NL); + htmltree.addContent(indent); if (includeAnnotations) { boolean foundAnnotations = - writer.writeAnnotationInfo(indent.length(), member, params[i]); + writer.addAnnotationInfo(indent.length(), member, params[i], + htmltree); if (foundAnnotations) { - writer.println(); - writer.print(indent); + htmltree.addContent(DocletConstants.NL); + htmltree.addContent(indent); } } - writeParam(member, params[i], (i == params.length - 1) && member.isVarArgs()); + addParam(member, params[i], (i == params.length - 1) && member.isVarArgs(), + htmltree); } - writer.print(')'); + htmltree.addContent(")"); } - protected void writeExceptions(ExecutableMemberDoc member) { + /** + * Add exceptions for the executable member. + * + * @param member the member to write exceptions for. + * @param htmltree the content tree to which the exceptions information will be added. + */ + protected void addExceptions(ExecutableMemberDoc member, Content htmltree) { Type[] exceptions = member.thrownExceptionTypes(); if(exceptions.length > 0) { LinkInfoImpl memberTypeParam = new LinkInfoImpl( - LinkInfoImpl.CONTEXT_MEMBER, member, false); + LinkInfoImpl.CONTEXT_MEMBER, member, false); int retlen = getReturnTypeLength(member); writer.getTypeParameterLinks(memberTypeParam); retlen += memberTypeParam.displayLength == 0 ? 0 : memberTypeParam.displayLength + 1; String indent = makeSpace(modifierString(member).length() + - member.name().length() + retlen - 4); - writer.println(); - writer.print(indent); - writer.print("throws "); + member.name().length() + retlen - 4); + htmltree.addContent(DocletConstants.NL); + htmltree.addContent(indent); + htmltree.addContent("throws "); indent += " "; - writer.printLink(new LinkInfoImpl( - LinkInfoImpl.CONTEXT_MEMBER, exceptions[0])); + Content link = new RawHtml(writer.getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_MEMBER, exceptions[0]))); + htmltree.addContent(link); for(int i = 1; i < exceptions.length; i++) { - writer.println(","); - writer.print(indent); - writer.printLink(new LinkInfoImpl( - LinkInfoImpl.CONTEXT_MEMBER, exceptions[i])); + htmltree.addContent(","); + htmltree.addContent(DocletConstants.NL); + htmltree.addContent(indent); + Content exceptionLink = new RawHtml(writer.getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_MEMBER, exceptions[i]))); + htmltree.addContent(exceptionLink); } } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractIndexWriter.java index eced2077e67..584cbd807c5 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractIndexWriter.java @@ -30,6 +30,8 @@ import java.util.*; import com.sun.javadoc.*; import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; /** * Generate Index for all the Member Names with Indexing in @@ -39,6 +41,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @see IndexBuilder * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class AbstractIndexWriter extends HtmlDocletWriter { @@ -78,175 +81,187 @@ public class AbstractIndexWriter extends HtmlDocletWriter { } /** - * Print the text "Index" in strong format in the navigation bar. + * Get the index label for navigation bar. + * + * @return a content tree for the tree label */ - protected void navLinkIndex() { - navCellRevStart(); - fontStyle("NavBarFont1Rev"); - strongText("doclet.Index"); - fontEnd(); - navCellEnd(); + protected Content getNavLinkIndex() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, indexLabel); + return li; } /** - * Generate the member information for the unicode character along with the + * Add the member information for the unicode character along with the * list of the members. * - * @param unicode Unicode for which member list information to be generated. - * @param memberlist List of members for the unicode character. + * @param unicode Unicode for which member list information to be generated + * @param memberlist List of members for the unicode character + * @param contentTree the content tree to which the information will be added */ - protected void generateContents(Character unicode, List memberlist) { - anchor("_" + unicode + "_"); - h2(); - strong(unicode.toString()); - h2End(); + protected void addContents(Character unicode, List memberlist, + Content contentTree) { + contentTree.addContent(getMarkerAnchor("_" + unicode + "_")); + Content headContent = new StringContent(unicode.toString()); + Content heading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, false, + HtmlStyle.title, headContent); + contentTree.addContent(heading); int memberListSize = memberlist.size(); // Display the list only if there are elements to be displayed. if (memberListSize > 0) { - dl(); + Content dl = new HtmlTree(HtmlTag.DL); for (int i = 0; i < memberListSize; i++) { Doc element = memberlist.get(i); if (element instanceof MemberDoc) { - printDescription((MemberDoc)element); + addDescription((MemberDoc)element, dl); } else if (element instanceof ClassDoc) { - printDescription((ClassDoc)element); + addDescription((ClassDoc)element, dl); } else if (element instanceof PackageDoc) { - printDescription((PackageDoc)element); + addDescription((PackageDoc)element, dl); } } - dlEnd(); + contentTree.addContent(dl); } - hr(); } - /** - * Print one line summary comment for the package. + * Add one line summary comment for the package. * - * @param pkg PackageDoc passed. + * @param pkg the package to be documented + * @param dlTree the content tree to which the description will be added */ - protected void printDescription(PackageDoc pkg) { - dt(); - printPackageLink(pkg, Util.getPackageName(pkg), true); - print(" - "); - print(configuration.getText("doclet.package") + " " + pkg.name()); - dtEnd(); - dd(); - printSummaryComment(pkg); - ddEnd(); + protected void addDescription(PackageDoc pkg, Content dlTree) { + Content link = getPackageLink(pkg, new StringContent(Util.getPackageName(pkg))); + Content dt = HtmlTree.DT(link); + dt.addContent(" - "); + dt.addContent(getResource("doclet.package")); + dt.addContent(" " + pkg.name()); + dlTree.addContent(dt); + Content dd = new HtmlTree(HtmlTag.DD); + addSummaryComment(pkg, dd); + dlTree.addContent(dd); } /** - * Print one line summary comment for the class. + * Add one line summary comment for the class. * - * @param cd ClassDoc passed. + * @param cd the class being documented + * @param dlTree the content tree to which the description will be added */ - protected void printDescription(ClassDoc cd) { - dt(); - printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_INDEX, cd, true)); - print(" - "); - printClassInfo(cd); - dtEnd(); - dd(); - printComment(cd); - ddEnd(); + protected void addDescription(ClassDoc cd, Content dlTree) { + Content link = new RawHtml( + getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_INDEX, cd, true))); + Content dt = HtmlTree.DT(link); + dt.addContent(" - "); + addClassInfo(cd, dt); + dlTree.addContent(dt); + Content dd = new HtmlTree(HtmlTag.DD); + addComment(cd, dd); + dlTree.addContent(dd); } /** - * Print the classkind(class, interface, exception, error of the class + * Add the classkind(class, interface, exception, error of the class * passed. * - * @param cd ClassDoc. + * @param cd the class being documented + * @param contentTree the content tree to which the class info will be added */ - protected void printClassInfo(ClassDoc cd) { - print(configuration.getText("doclet.in", - Util.getTypeName(configuration, cd, false), - getPackageLink(cd.containingPackage(), + protected void addClassInfo(ClassDoc cd, Content contentTree) { + contentTree.addContent(getResource("doclet.in", + Util.getTypeName(configuration, cd, false), + getPackageLinkString(cd.containingPackage(), Util.getPackageName(cd.containingPackage()), false))); } - /** - * Generate Description for Class, Field, Method or Constructor. - * for Java.* Packages Class Members. + * Add description for Class, Field, Method or Constructor. * - * @param member MemberDoc for the member of the Class Kind. - * @see com.sun.javadoc.MemberDoc + * @param member MemberDoc for the member of the Class Kind + * @param dlTree the content tree to which the description will be added */ - protected void printDescription(MemberDoc member) { + protected void addDescription(MemberDoc member, Content dlTree) { String name = (member instanceof ExecutableMemberDoc)? member.name() + ((ExecutableMemberDoc)member).flatSignature() : member.name(); if (name.indexOf("<") != -1 || name.indexOf(">") != -1) { name = Util.escapeHtmlChars(name); } - ClassDoc containing = member.containingClass(); - dt(); - printDocLink(LinkInfoImpl.CONTEXT_INDEX, member, name, true); - println(" - "); - printMemberDesc(member); - println(); - dtEnd(); - dd(); - printComment(member); - ddEnd(); - println(); + Content span = HtmlTree.SPAN(HtmlStyle.strong, + getDocLink(LinkInfoImpl.CONTEXT_INDEX, member, name)); + Content dt = HtmlTree.DT(span); + dt.addContent(" - "); + addMemberDesc(member, dt); + dlTree.addContent(dt); + Content dd = new HtmlTree(HtmlTag.DD); + addComment(member, dd); + dlTree.addContent(dd); } - /** - * Print comment for each element in the index. If the element is deprecated + * Add comment for each element in the index. If the element is deprecated * and it has a @deprecated tag, use that comment. Else if the containing * class for this element is deprecated, then add the word "Deprecated." at * the start and then print the normal comment. * - * @param element Index element. + * @param element Index element + * @param contentTree the content tree to which the comment will be added */ - protected void printComment(ProgramElementDoc element) { + protected void addComment(ProgramElementDoc element, Content contentTree) { Tag[] tags; + Content span = HtmlTree.SPAN(HtmlStyle.strong, deprecatedPhrase); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.block); if (Util.isDeprecated(element)) { - strongText("doclet.Deprecated"); space(); + div.addContent(span); if ((tags = element.tags("deprecated")).length > 0) - printInlineDeprecatedComment(element, tags[0]); + addInlineDeprecatedComment(element, tags[0], div); + contentTree.addContent(div); } else { ClassDoc cont = element.containingClass(); while (cont != null) { if (Util.isDeprecated(cont)) { - strongText("doclet.Deprecated"); space(); + div.addContent(span); + contentTree.addContent(div); break; } cont = cont.containingClass(); } - printSummaryComment(element); + addSummaryComment(element, contentTree); } } /** - * Print description about the Static Varible/Method/Constructor for a + * Add description about the Static Varible/Method/Constructor for a * member. * - * @param member MemberDoc for the member within the Class Kind. - * @see com.sun.javadoc.MemberDoc + * @param member MemberDoc for the member within the Class Kind + * @param contentTree the content tree to which the member description will be added */ - protected void printMemberDesc(MemberDoc member) { + protected void addMemberDesc(MemberDoc member, Content contentTree) { ClassDoc containing = member.containingClass(); - String classdesc = Util.getTypeName(configuration, containing, true) + " " + - getPreQualifiedClassLink(LinkInfoImpl.CONTEXT_INDEX, containing, - false); + String classdesc = Util.getTypeName( + configuration, containing, true) + " "; if (member.isField()) { if (member.isStatic()) { - printText("doclet.Static_variable_in", classdesc); + contentTree.addContent( + getResource("doclet.Static_variable_in", classdesc)); } else { - printText("doclet.Variable_in", classdesc); + contentTree.addContent( + getResource("doclet.Variable_in", classdesc)); } } else if (member.isConstructor()) { - printText("doclet.Constructor_for", classdesc); + contentTree.addContent( + getResource("doclet.Constructor_for", classdesc)); } else if (member.isMethod()) { if (member.isStatic()) { - printText("doclet.Static_method_in", classdesc); + contentTree.addContent( + getResource("doclet.Static_method_in", classdesc)); } else { - printText("doclet.Method_in", classdesc); + contentTree.addContent( + getResource("doclet.Method_in", classdesc)); } } + addPreQualifiedClassLink(LinkInfoImpl.CONTEXT_INDEX, containing, + false, contentTree); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java index c1cbbd775e9..345c8a948c0 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java @@ -25,10 +25,11 @@ package com.sun.tools.doclets.formats.html; -import java.lang.reflect.Modifier; import java.util.*; - +import java.lang.reflect.Modifier; import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.taglets.*; @@ -60,36 +61,125 @@ public abstract class AbstractMemberWriter { /*** abstracts ***/ - public abstract void printSummaryLabel(); + /** + * Add the summary label for the member. + * + * @param memberTree the content tree to which the label will be added + */ + public abstract void addSummaryLabel(Content memberTree); - public abstract void printTableSummary(); + /** + * Get the summary for the member summary table. + * + * @return a string for the table summary + */ + public abstract String getTableSummary(); - public abstract void printSummaryTableHeader(ProgramElementDoc member); + /** + * Get the caption for the member summary table. + * + * @return a string for the table caption + */ + public abstract String getCaption(); - public abstract void printInheritedSummaryLabel(ClassDoc cd); + /** + * Get the summary table header for the member. + * + * @param member the member to be documented + * @return the summary table header + */ + public abstract String[] getSummaryTableHeader(ProgramElementDoc member); - public abstract void printSummaryAnchor(ClassDoc cd); + /** + * Add inherited summary lable for the member. + * + * @param cd the class doc to which to link to + * @param inheritedTree the content tree to which the inherited summary label will be added + */ + public abstract void addInheritedSummaryLabel(ClassDoc cd, Content inheritedTree); - public abstract void printInheritedSummaryAnchor(ClassDoc cd); + /** + * Add the anchor for the summary section of the member. + * + * @param cd the class doc to be documented + * @param memberTree the content tree to which the summary anchor will be added + */ + public abstract void addSummaryAnchor(ClassDoc cd, Content memberTree); - protected abstract void printSummaryType(ProgramElementDoc member); + /** + * Add the anchor for the inherited summary section of the member. + * + * @param cd the class doc to be documented + * @param inheritedTree the content tree to which the inherited summary anchor will be added + */ + public abstract void addInheritedSummaryAnchor(ClassDoc cd, Content inheritedTree); - protected void writeSummaryLink(ClassDoc cd, ProgramElementDoc member) { - writeSummaryLink(LinkInfoImpl.CONTEXT_MEMBER, cd, member); + /** + * Add the summary type for the member. + * + * @param member the member to be documented + * @param tdSummaryType the content tree to which the type will be added + */ + protected abstract void addSummaryType(ProgramElementDoc member, + Content tdSummaryType); + + /** + * Add the summary link for the member. + * + * @param cd the class doc to be documented + * @param member the member to be documented + * @param tdSummary the content tree to which the link will be added + */ + protected void addSummaryLink(ClassDoc cd, ProgramElementDoc member, + Content tdSummary) { + addSummaryLink(LinkInfoImpl.CONTEXT_MEMBER, cd, member, tdSummary); } - protected abstract void writeSummaryLink(int context, - ClassDoc cd, - ProgramElementDoc member); + /** + * Add the summary link for the member. + * + * @param context the id of the context where the link will be printed + * @param cd the class doc to be documented + * @param member the member to be documented + * @param tdSummary the content tree to which the summary link will be added + */ + protected abstract void addSummaryLink(int context, + ClassDoc cd, ProgramElementDoc member, Content tdSummary); - protected abstract void writeInheritedSummaryLink(ClassDoc cd, - ProgramElementDoc member); + /** + * Add the inherited summary link for the member. + * + * @param cd the class doc to be documented + * @param member the member to be documented + * @param linksTree the content tree to which the inherited summary link will be added + */ + protected abstract void addInheritedSummaryLink(ClassDoc cd, + ProgramElementDoc member, Content linksTree); - protected abstract void writeDeprecatedLink(ProgramElementDoc member); + /** + * Get the deprecated link. + * + * @param member the member being linked to + * @return a content tree representing the link + */ + protected abstract Content getDeprecatedLink(ProgramElementDoc member); - protected abstract void printNavSummaryLink(ClassDoc cd, boolean link); + /** + * Get the navigation summary link. + * + * @param cd the class doc to be documented + * @param link true if its a link else the label to be printed + * @return a content tree for the navigation summary link. + */ + protected abstract Content getNavSummaryLink(ClassDoc cd, boolean link); - protected abstract void printNavDetailLink(boolean link); + /** + * Add the navigation detail link. + * + * @param link true if its a link else the label to be printed + * @param liNav the content tree to which the navigation detail link will be added + */ + protected abstract void addNavDetailLink(boolean link, Content liNav); /*** ***/ @@ -108,6 +198,17 @@ public abstract class AbstractMemberWriter { writer.displayLength += str.length(); } + /** + * Add the member name to the content tree and modifies the display length. + * + * @param name the member name to be added to the content tree. + * @param htmltree the content tree to which the name will be added. + */ + protected void addName(String name, Content htmltree) { + htmltree.addContent(name); + writer.displayLength += name.length(); + } + /** * Return a string describing the access modifier flags. * Don't include native or synchronized. @@ -131,18 +232,24 @@ public abstract class AbstractMemberWriter { return type; } - protected void printModifiers(MemberDoc member) { + /** + * Add the modifier for the member. + * + * @param member the member for which teh modifier will be added. + * @param htmltree the content tree to which the modifier information will be added. + */ + protected void addModifiers(MemberDoc member, Content htmltree) { String mod = modifierString(member); // According to JLS, we should not be showing public modifier for // interface methods. if ((member.isField() || member.isMethod()) && writer instanceof ClassWriterImpl && - ((ClassWriterImpl) writer).getClassDoc().isInterface()) { + ((ClassWriterImpl) writer).getClassDoc().isInterface()) { mod = Util.replaceText(mod, "public", "").trim(); } if(mod.length() > 0) { - print(mod); - print(' '); + htmltree.addContent(mod); + htmltree.addContent(writer.getSpace()); } } @@ -158,66 +265,43 @@ public abstract class AbstractMemberWriter { } /** - * Print 'static' if static and type link. - */ - protected void printStaticAndType(boolean isStatic, Type type) { - writer.printTypeSummaryHeader(); - if (isStatic) { - print("static"); - } - writer.space(); - if (type != null) { - writer.printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, - type)); - } - writer.printTypeSummaryFooter(); - } - - /** - * Print the modifier and type for the member in the member summary. + * Add the modifier and type for the member in the member summary. * - * @param member the member to print the type for. - * @param type the type to print. + * @param member the member to add the type for + * @param type the type to add + * @param tdSummaryType the content tree to which the modified and type will be added */ - protected void printModifierAndType(ProgramElementDoc member, Type type) { - writer.printTypeSummaryHeader(); - printModifier(member); + protected void addModifierAndType(ProgramElementDoc member, Type type, + Content tdSummaryType) { + HtmlTree code = new HtmlTree(HtmlTag.CODE); + addModifier(member, code); if (type == null) { - writer.space(); if (member.isClass()) { - print("class"); + code.addContent("class"); } else { - print("interface"); + code.addContent("interface"); } + code.addContent(writer.getSpace()); } else { if (member instanceof ExecutableMemberDoc && ((ExecutableMemberDoc) member).typeParameters().length > 0) { //Code to avoid ugly wrapping in member summary table. - writer.table(0,0,0); - writer.trAlignVAlign("right", ""); - writer.tdNowrap(); - writer.font("-1"); - writer.code(); - int displayLength = ((AbstractExecutableMemberWriter) this). - writeTypeParameters((ExecutableMemberDoc) member); + int displayLength = ((AbstractExecutableMemberWriter) this).addTypeParameters( + (ExecutableMemberDoc) member, code); if (displayLength > 10) { - writer.br(); + code.addContent(new HtmlTree(HtmlTag.BR)); } - writer.printLink(new LinkInfoImpl( - LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type)); - writer.codeEnd(); - writer.fontEnd(); - writer.tdEnd(); - writer.trEnd(); - writer.tableEnd(); + code.addContent(new RawHtml( + writer.getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type)))); } else { - writer.space(); - writer.printLink(new LinkInfoImpl( - LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type)); + code.addContent(new RawHtml( + writer.getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type)))); } } - writer.printTypeSummaryFooter(); + tdSummaryType.addContent(code); } private void printModifier(ProgramElementDoc member) { @@ -238,25 +322,53 @@ public abstract class AbstractMemberWriter { } /** - * Print the deprecated output for the given member. + * Add the modifier for the member. * - * @param member the member being documented. + * @param member the member to add the type for + * @param code the content tree to which the modified will be added */ - protected void printDeprecated(ProgramElementDoc member) { - String output = (new DeprecatedTaglet()).getTagletOutput(member, - writer.getTagletWriterInstance(false)).toString().trim(); - if (!output.isEmpty()) { - writer.printMemberDetailsListStartTag(); - writer.print(output); + private void addModifier(ProgramElementDoc member, Content code) { + if (member.isProtected()) { + code.addContent("protected "); + } else if (member.isPrivate()) { + code.addContent("private "); + } else if (!member.isPublic()) { // Package private + code.addContent(configuration().getText("doclet.Package_private")); + code.addContent(" "); + } + if (member.isMethod() && ((MethodDoc)member).isAbstract()) { + code.addContent("abstract "); + } + if (member.isStatic()) { + code.addContent("static "); } } - protected void printComment(ProgramElementDoc member) { + /** + * Add the deprecated information for the given member. + * + * @param member the member being documented. + * @param contentTree the content tree to which the deprecated information will be added. + */ + protected void addDeprecatedInfo(ProgramElementDoc member, Content contentTree) { + String output = (new DeprecatedTaglet()).getTagletOutput(member, + writer.getTagletWriterInstance(false)).toString().trim(); + if (!output.isEmpty()) { + Content deprecatedContent = new RawHtml(output); + Content div = HtmlTree.DIV(HtmlStyle.block, deprecatedContent); + contentTree.addContent(div); + } + } + + /** + * Add the comment for the given member. + * + * @param member the member being documented. + * @param contentTree the content tree to which the comment will be added. + */ + protected void addComment(ProgramElementDoc member, Content htmltree) { if (member.inlineTags().length > 0) { - writer.printMemberDetailsListStartTag(); - writer.dd(); - writer.printInlineComment(member); - writer.ddEnd(); + writer.addInlineComment(member, htmltree); } } @@ -264,67 +376,19 @@ public abstract class AbstractMemberWriter { return member.name(); } - protected void printHead(MemberDoc member) { - writer.h3(); - writer.print(member.name()); - writer.h3End(); - } - - protected void printFullComment(ProgramElementDoc member) { - if(configuration().nocomment){ - return; - } - writer.dl(); - print(((TagletOutputImpl) - (new DeprecatedTaglet()).getTagletOutput(member, - writer.getTagletWriterInstance(false))).toString()); - printCommentAndTags(member); - writer.dlEnd(); - } - - protected void printCommentAndTags(ProgramElementDoc member) { - printComment(member); - writer.printTags(member); + /** + * Get the header for the section. + * + * @param member the member being documented. + * @return a header content for the section. + */ + protected Content getHead(MemberDoc member) { + Content memberContent = new RawHtml(member.name()); + Content heading = HtmlTree.HEADING(HtmlConstants.MEMBER_HEADING, memberContent); + return heading; } /** - * Write the member footer. - */ - protected void printMemberFooter() { - writer.printMemberDetailsListEndTag(); - assert !writer.getMemberDetailsListPrinted(); - } - - /** - * Forward to containing writer - */ - public void printSummaryHeader(ClassDoc cd) { - printedSummaryHeader = true; - writer.printSummaryHeader(this, cd); - } - - /** - * Forward to containing writer - */ - public void printInheritedSummaryHeader(ClassDoc cd) { - writer.printInheritedSummaryHeader(this, cd); - } - - /** - * Forward to containing writer - */ - public void printInheritedSummaryFooter(ClassDoc cd) { - writer.printInheritedSummaryFooter(this, cd); - } - - /** - * Forward to containing writer - */ - public void printSummaryFooter(ClassDoc cd) { - writer.printSummaryFooter(this, cd); - } - - /** * Return true if the given ProgramElement is inherited * by the class that is being documented. * @@ -340,102 +404,134 @@ public abstract class AbstractMemberWriter { return true; } - /** - * Generate the code for listing the deprecated APIs. Create the table - * format for listing the API. Call methods from the sub-class to complete - * the generation. + * Add deprecated information to the documentation tree + * + * @param deprmembers list of deprecated members + * @param headingKey the caption for the deprecated members table + * @param tableSummary the summary for the deprecated members table + * @param tableHeader table headers for the deprecated members table + * @param contentTree the content tree to which the deprecated members table will be added */ - protected void printDeprecatedAPI(List deprmembers, String headingKey, String tableSummary, String[] tableHeader) { + protected void addDeprecatedAPI(List deprmembers, String headingKey, + String tableSummary, String[] tableHeader, Content contentTree) { if (deprmembers.size() > 0) { - writer.tableIndexSummary(tableSummary); - writer.tableCaptionStart(); - writer.printText(headingKey); - writer.tableCaptionEnd(); - writer.summaryTableHeader(tableHeader, "col"); + Content table = HtmlTree.TABLE(0, 3, 0, tableSummary, + writer.getTableCaption(configuration().getText(headingKey))); + table.addContent(writer.getSummaryTableHeader(tableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); for (int i = 0; i < deprmembers.size(); i++) { ProgramElementDoc member =(ProgramElementDoc)deprmembers.get(i); - writer.trBgcolorStyle("white", "TableRowColor"); - writer.summaryRow(0); - writeDeprecatedLink(member); - writer.br(); - writer.printNbsps(); + HtmlTree td = HtmlTree.TD(HtmlStyle.colOne, getDeprecatedLink(member)); if (member.tags("deprecated").length > 0) - writer.printInlineDeprecatedComment(member, member.tags("deprecated")[0]); - writer.space(); - writer.summaryRowEnd(); - writer.trEnd(); + writer.addInlineDeprecatedComment(member, + member.tags("deprecated")[0], td); + HtmlTree tr = HtmlTree.TR(td); + if (i%2 == 0) + tr.addStyle(HtmlStyle.altColor); + else + tr.addStyle(HtmlStyle.rowColor); + tbody.addContent(tr); } - writer.tableEnd(); - writer.space(); - writer.p(); + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + Content ul = HtmlTree.UL(HtmlStyle.blockList, li); + contentTree.addContent(ul); } } /** - * Print use info. + * Add use information to the documentation tree. + * + * @param mems list of program elements for which the use information will be added + * @param heading the section heading + * @param tableSummary the summary for the use table + * @param contentTree the content tree to which the use information will be added */ - protected void printUseInfo(List mems, String heading, String tableSummary) { + protected void addUseInfo(List mems, + String heading, String tableSummary, Content contentTree) { if (mems == null) { return; } List members = mems; boolean printedUseTableHeader = false; if (members.size() > 0) { - writer.tableIndexSummary(tableSummary); - writer.tableSubCaptionStart(); - writer.print(heading); - writer.tableCaptionEnd(); - for (Iterator it = members.iterator(); it.hasNext(); ) { + Content table = HtmlTree.TABLE(0, 3, 0, tableSummary, + writer.getTableCaption(heading)); + Content tbody = new HtmlTree(HtmlTag.TBODY); + Iterator it = members.iterator(); + for (int i = 0; it.hasNext(); i++) { ProgramElementDoc pgmdoc = it.next(); ClassDoc cd = pgmdoc.containingClass(); if (!printedUseTableHeader) { - // Passing ProgramElementDoc helps decides printing - // interface or class header in case of nested classes. - this.printSummaryTableHeader(pgmdoc); + table.addContent(writer.getSummaryTableHeader( + this.getSummaryTableHeader(pgmdoc), "col")); printedUseTableHeader = true; } - - writer.printSummaryLinkType(this, pgmdoc); + HtmlTree tr = new HtmlTree(HtmlTag.TR); + if (i % 2 == 0) { + tr.addStyle(HtmlStyle.altColor); + } else { + tr.addStyle(HtmlStyle.rowColor); + } + HtmlTree tdFirst = new HtmlTree(HtmlTag.TD); + tdFirst.addStyle(HtmlStyle.colFirst); + writer.addSummaryType(this, pgmdoc, tdFirst); + tr.addContent(tdFirst); + HtmlTree tdLast = new HtmlTree(HtmlTag.TD); + tdLast.addStyle(HtmlStyle.colLast); if (cd != null && !(pgmdoc instanceof ConstructorDoc) - && !(pgmdoc instanceof ClassDoc)) { - // Add class context - writer.strong(cd.name() + "."); + && !(pgmdoc instanceof ClassDoc)) { + HtmlTree name = new HtmlTree(HtmlTag.SPAN); + name.addStyle(HtmlStyle.strong); + name.addContent(cd.name() + "."); + tdLast.addContent(name); } - writeSummaryLink( - pgmdoc instanceof ClassDoc ? - LinkInfoImpl.CONTEXT_CLASS_USE : LinkInfoImpl.CONTEXT_MEMBER, - cd, pgmdoc); - writer.printSummaryLinkComment(this, pgmdoc); + addSummaryLink(pgmdoc instanceof ClassDoc ? + LinkInfoImpl.CONTEXT_CLASS_USE : LinkInfoImpl.CONTEXT_MEMBER, + cd, pgmdoc, tdLast); + writer.addSummaryLinkComment(this, pgmdoc, tdLast); + tr.addContent(tdLast); + tbody.addContent(tr); } - writer.tableEnd(); - writer.space(); - writer.p(); + table.addContent(tbody); + contentTree.addContent(table); } } - protected void navDetailLink(List members) { - printNavDetailLink(members.size() > 0? true: false); + /** + * Add the navigation detail link. + * + * @param members the members to be linked + * @param liNav the content tree to which the navigation detail link will be added + */ + protected void addNavDetailLink(List members, Content liNav) { + addNavDetailLink(members.size() > 0 ? true : false, liNav); } - - protected void navSummaryLink(List members, - VisibleMemberMap visibleMemberMap) { + /** + * Add the navigation summary link. + * + * @param members members to be linked + * @param visibleMemberMap the visible inherited members map + * @param liNav the content tree to which the navigation summary link will be added + */ + protected void addNavSummaryLink(List members, + VisibleMemberMap visibleMemberMap, Content liNav) { if (members.size() > 0) { - printNavSummaryLink(null, true); + liNav.addContent(getNavSummaryLink(null, true)); return; - } else { - ClassDoc icd = classdoc.superclass(); - while (icd != null) { - List inhmembers = visibleMemberMap.getMembersFor(icd); - if (inhmembers.size() > 0) { - printNavSummaryLink(icd, true); - return; - } - icd = icd.superclass(); - } } - printNavSummaryLink(null, false); + ClassDoc icd = classdoc.superclass(); + while (icd != null) { + List inhmembers = visibleMemberMap.getMembersFor(icd); + if (inhmembers.size() > 0) { + liNav.addContent(getNavSummaryLink(icd, true)); + return; + } + icd = icd.superclass(); + } + liNav.addContent(getNavSummaryLink(null, false)); } protected void serialWarning(SourcePosition pos, String key, String a1, String a2) { @@ -453,12 +549,109 @@ public abstract class AbstractMemberWriter { } /** - * {@inheritDoc} + * Add the member summary for the given class. + * + * @param classDoc the class that is being documented + * @param member the member being documented + * @param firstSentenceTags the first sentence tags to be added to the summary + * @param tableTree the content tree to which the documentation will be added + * @param counter the counter for determing style for the table row */ - public void writeMemberSummary(ClassDoc classDoc, ProgramElementDoc member, - Tag[] firstSentenceTags, boolean isFirst, boolean isLast) { - writer.printSummaryLinkType(this, member); - writeSummaryLink(classDoc, member); - writer.printSummaryLinkComment(this, member, firstSentenceTags); + public void addMemberSummary(ClassDoc classDoc, ProgramElementDoc member, + Tag[] firstSentenceTags, Content tableTree, int counter) { + HtmlTree tdSummaryType = new HtmlTree(HtmlTag.TD); + tdSummaryType.addStyle(HtmlStyle.colFirst); + writer.addSummaryType(this, member, tdSummaryType); + HtmlTree tdSummary = new HtmlTree(HtmlTag.TD); + setSummaryColumnStyle(tdSummary); + addSummaryLink(classDoc, member, tdSummary); + writer.addSummaryLinkComment(this, member, firstSentenceTags, tdSummary); + HtmlTree tr = HtmlTree.TR(tdSummaryType); + tr.addContent(tdSummary); + if (counter%2 == 0) + tr.addStyle(HtmlStyle.altColor); + else + tr.addStyle(HtmlStyle.rowColor); + tableTree.addContent(tr); + } + + /** + * Set the style for the summary column. + * + * @param tdTree the column for which the style will be set + */ + public void setSummaryColumnStyle(HtmlTree tdTree) { + tdTree.addStyle(HtmlStyle.colLast); + } + + /** + * Add inherited member summary for the given class and member. + * + * @param classDoc the class the inherited member belongs to + * @param nestedClass the inherited member that is summarized + * @param isFirst true if this is the first member in the list + * @param isLast true if this is the last member in the list + * @param linksTree the content tree to which the summary will be added + */ + public void addInheritedMemberSummary(ClassDoc classDoc, + ProgramElementDoc nestedClass, boolean isFirst, boolean isLast, + Content linksTree) { + writer.addInheritedMemberSummary(this, classDoc, nestedClass, isFirst, + linksTree); + } + + /** + * Get the inherited summary header for the given class. + * + * @param classDoc the class the inherited member belongs to + * @return a content tree for the inherited summary header + */ + public Content getInheritedSummaryHeader(ClassDoc classDoc) { + Content inheritedTree = writer.getMemberTreeHeader(); + writer.addInheritedSummaryHeader(this, classDoc, inheritedTree); + return inheritedTree; + } + + /** + * Get the inherited summary links tree. + * + * @return a content tree for the inherited summary links + */ + public Content getInheritedSummaryLinksTree() { + return new HtmlTree(HtmlTag.CODE); + } + + /** + * Get the summary table tree for the given class. + * + * @param classDoc the class for which the summary table is generated + * @return a content tree for the summary table + */ + public Content getSummaryTableTree(ClassDoc classDoc) { + return writer.getSummaryTableTree(this, classDoc); + } + + /** + * Get the member tree to be documented. + * + * @param memberTree the content tree of member to be documented + * @return a content tree that will be added to the class documentation + */ + public Content getMemberTree(Content memberTree) { + return writer.getMemberTree(memberTree); + } + + /** + * Get the member tree to be documented. + * + * @param memberTree the content tree of member to be documented + * @param isLastContent true if the content to be added is the last content + * @return a content tree that will be added to the class documentation + */ + public Content getMemberTree(Content memberTree, boolean isLastContent) { + if (isLastContent) + return HtmlTree.UL(HtmlStyle.blockListLast, memberTree); + else + return HtmlTree.UL(HtmlStyle.blockList, memberTree); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java index 2daa107c635..87f3575be70 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java @@ -25,9 +25,11 @@ package com.sun.tools.doclets.formats.html; -import com.sun.javadoc.*; import java.io.*; import java.util.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; /** * Abstract class to generate the overview files in @@ -56,105 +58,127 @@ public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter { packages = configuration.packages; } - protected abstract void printNavigationBarHeader(); - - protected abstract void printNavigationBarFooter(); - - protected abstract void printOverviewHeader(); - - protected abstract void printIndexHeader(String text, String tableSummary); - - protected abstract void printIndexRow(PackageDoc pkg); - - protected abstract void printIndexFooter(); + /** + * Adds the navigation bar header to the documentation tree. + * + * @param body the document tree to which the navigation bar header will be added + */ + protected abstract void addNavigationBarHeader(Content body); /** - * Generate the contants in the package index file. Call appropriate + * Adds the navigation bar footer to the documentation tree. + * + * @param body the document tree to which the navigation bar footer will be added + */ + protected abstract void addNavigationBarFooter(Content body); + + /** + * Adds the overview header to the documentation tree. + * + * @param body the document tree to which the overview header will be added + */ + protected abstract void addOverviewHeader(Content body); + + /** + * Adds the packages list to the documentation tree. + * + * @param packages an array of packagedoc objects + * @param text caption for the table + * @param tableSummary summary for the table + * @param body the document tree to which the packages list will be added + */ + protected abstract void addPackagesList(PackageDoc[] packages, String text, + String tableSummary, Content body); + + /** + * Generate and prints the contents in the package index file. Call appropriate * methods from the sub-class in order to generate Frame or Non * Frame format. + * * @param title the title of the window. * @param includeScript boolean set true if windowtitle script is to be included */ - protected void generatePackageIndexFile(String title, boolean includeScript) throws IOException { + protected void buildPackageIndexFile(String title, boolean includeScript) throws IOException { String windowOverview = configuration.getText(title); - printHtmlHeader(windowOverview, - configuration.metakeywords.getOverviewMetaKeywords(title, - configuration.doctitle), - includeScript); - printNavigationBarHeader(); - printOverviewHeader(); - - generateIndex(); - - printOverview(); - - printNavigationBarFooter(); - printBodyHtmlEnd(); + Content body = getBody(includeScript, getWindowTitle(windowOverview)); + addNavigationBarHeader(body); + addOverviewHeader(body); + addIndex(body); + addOverview(body); + addNavigationBarFooter(body); + printHtmlDocument(configuration.metakeywords.getOverviewMetaKeywords(title, + configuration.doctitle), includeScript, body); } /** - * Default to no overview, overwrite to add overview. + * Default to no overview, override to add overview. + * + * @param body the document tree to which the overview will be added */ - protected void printOverview() throws IOException { + protected void addOverview(Content body) throws IOException { } /** - * Generate the frame or non-frame package index. + * Adds the frame or non-frame package index to the documentation tree. + * + * @param body the document tree to which the index will be added */ - protected void generateIndex() { - printIndexContents(packages, "doclet.Package_Summary", + protected void addIndex(Content body) { + addIndexContents(packages, "doclet.Package_Summary", configuration.getText("doclet.Member_Table_Summary", configuration.getText("doclet.Package_Summary"), - configuration.getText("doclet.packages"))); + configuration.getText("doclet.packages")), body); } /** - * Generate code for package index contents. Call appropriate methods from - * the sub-classes. + * Adds package index contents. Call appropriate methods from + * the sub-classes. Adds it to the body HtmlTree * - * @param packages Array of packages to be documented. - * @param text String which will be used as the heading. + * @param packages array of packages to be documented + * @param text string which will be used as the heading + * @param tableSummary summary for the table + * @param body the document tree to which the index contents will be added */ - protected void printIndexContents(PackageDoc[] packages, String text, String tableSummary) { + protected void addIndexContents(PackageDoc[] packages, String text, + String tableSummary, Content body) { if (packages.length > 0) { Arrays.sort(packages); - printIndexHeader(text, tableSummary); - printAllClassesPackagesLink(); - for(int i = 0; i < packages.length; i++) { - if (packages[i] != null) { - printIndexRow(packages[i]); - } - } - printIndexFooter(); + addAllClassesLink(body); + addPackagesList(packages, text, tableSummary, body); } } /** - * Print the doctitle, if it is specified on the command line. + * Adds the doctitle to the documentation tree, if it is specified on the command line. + * + * @param body the document tree to which the title will be added */ - protected void printConfigurationTitle() { + protected void addConfigurationTitle(Content body) { if (configuration.doctitle.length() > 0) { - center(); - h1(configuration.doctitle); - centerEnd(); + Content title = new RawHtml(configuration.doctitle); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, + HtmlStyle.title, title); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + body.addContent(div); } } /** - * Highlight "Overview" in the strong format, in the navigation bar as this - * is the overview page. + * Returns highlighted "Overview", in the navigation bar as this is the + * overview page. + * + * @return a Content object to be added to the documentation tree */ - protected void navLinkContents() { - navCellRevStart(); - fontStyle("NavBarFont1Rev"); - strongText("doclet.Overview"); - fontEnd(); - navCellEnd(); + protected Content getNavLinkContents() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, overviewLabel); + return li; } /** * Do nothing. This will be overridden in PackageIndexFrameWriter. + * + * @param body the document tree to which the all classes link will be added */ - protected void printAllClassesPackagesLink() { + protected void addAllClassesLink(Content body) { } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractTreeWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractTreeWriter.java index 5c6fc40e783..58b58d7ddd2 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractTreeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractTreeWriter.java @@ -25,11 +25,12 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.util.*; - -import com.sun.javadoc.*; import java.io.*; import java.util.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.javadoc.*; /** * Abstract class to print the class hierarchy page for all the Classes. This @@ -46,6 +47,8 @@ public abstract class AbstractTreeWriter extends HtmlDocletWriter { */ protected final ClassTree classtree; + private static final String LI_CIRCLE = "circle"; + /** * Constructor initilises classtree variable. This constructor will be used * while generating global tree file "overview-tree.html". @@ -87,55 +90,64 @@ public abstract class AbstractTreeWriter extends HtmlDocletWriter { } /** - * Generate each level of the class tree. For each sub-class or + * Add each level of the class tree. For each sub-class or * sub-interface indents the next level information. - * Recurses itself to generate subclasses info. - * To iterate is human, to recurse is divine - L. Peter Deutsch. + * Recurses itself to add subclasses info. * - * @param parent the superclass or superinterface of the list. - * @param list list of the sub-classes at this level. - * @param isEnum true if we are generating a tree for enums. + * @param parent the superclass or superinterface of the list + * @param list list of the sub-classes at this level + * @param isEnum true if we are generating a tree for enums + * @param contentTree the content tree to which the level information will be added */ - protected void generateLevelInfo(ClassDoc parent, List list, - boolean isEnum) { - if (list.size() > 0) { - ul(); - for (int i = 0; i < list.size(); i++) { + protected void addLevelInfo(ClassDoc parent, List list, + boolean isEnum, Content contentTree) { + int size = list.size(); + if (size > 0) { + Content ul = new HtmlTree(HtmlTag.UL); + for (int i = 0; i < size; i++) { ClassDoc local = list.get(i); - printPartialInfo(local); - printExtendsImplements(parent, local); - generateLevelInfo(local, classtree.subs(local, isEnum), - isEnum); // Recurse + HtmlTree li = new HtmlTree(HtmlTag.LI); + li.addAttr(HtmlAttr.TYPE, LI_CIRCLE); + addPartialInfo(local, li); + addExtendsImplements(parent, local, li); + addLevelInfo(local, classtree.subs(local, isEnum), + isEnum, li); // Recurse + ul.addContent(li); } - ulEnd(); + contentTree.addContent(ul); } } /** - * Generate the heading for the tree depending upon tree type if it's a - * Class Tree or Interface tree and also print the tree. + * Add the heading for the tree depending upon tree type if it's a + * Class Tree or Interface tree. * * @param list List of classes which are at the most base level, all the - * other classes in this run will derive from these classes. - * @param heading Heading for the tree. + * other classes in this run will derive from these classes + * @param heading heading for the tree + * @param div the content tree to which the tree will be added */ - protected void generateTree(List list, String heading) { + protected void addTree(List list, String heading, Content div) { if (list.size() > 0) { ClassDoc firstClassDoc = list.get(0); - printTreeHeading(heading); - generateLevelInfo(!firstClassDoc.isInterface()? firstClassDoc : null, - list, - list == classtree.baseEnums()); + Content headingContent = getResource(heading); + div.addContent(HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, true, + headingContent)); + addLevelInfo(!firstClassDoc.isInterface()? firstClassDoc : null, + list, list == classtree.baseEnums(), div); } } /** - * Print the information regarding the classes which this class extends or + * Add information regarding the classes which this class extends or * implements. * - * @param cd The classdoc under consideration. + * @param parent the parent class of the class being documented + * @param cd the classdoc under consideration + * @param contentTree the content tree to which the information will be added */ - protected void printExtendsImplements(ClassDoc parent, ClassDoc cd) { + protected void addExtendsImplements(ClassDoc parent, ClassDoc cd, + Content contentTree) { ClassDoc[] interfaces = cd.interfaces(); if (interfaces.length > (cd.isInterface()? 1 : 0)) { Arrays.sort(interfaces); @@ -148,53 +160,43 @@ public abstract class AbstractTreeWriter extends HtmlDocletWriter { } if (counter == 0) { if (cd.isInterface()) { - print(" (" + configuration.getText("doclet.also") + " extends "); + contentTree.addContent(" ("); + contentTree.addContent(getResource("doclet.also")); + contentTree.addContent(" extends "); } else { - print(" (implements "); + contentTree.addContent(" (implements "); } } else { - print(", "); + contentTree.addContent(", "); } - printPreQualifiedClassLink(LinkInfoImpl.CONTEXT_TREE, - interfaces[i]); + addPreQualifiedClassLink(LinkInfoImpl.CONTEXT_TREE, + interfaces[i], contentTree); counter++; } } if (counter > 0) { - println(")"); + contentTree.addContent(")"); } } } /** - * Print information about the class kind, if it's a "class" or "interface". + * Add information about the class kind, if it's a "class" or "interface". * - * @param cd classdoc. + * @param cd the class being documented + * @param contentTree the content tree to which the information will be added */ - protected void printPartialInfo(ClassDoc cd) { - li("circle"); - printPreQualifiedStrongClassLink(LinkInfoImpl.CONTEXT_TREE, cd); + protected void addPartialInfo(ClassDoc cd, Content contentTree) { + addPreQualifiedStrongClassLink(LinkInfoImpl.CONTEXT_TREE, cd, contentTree); } /** - * Print the heading for the tree. + * Get the tree label for the navigation bar. * - * @param heading Heading for the tree. + * @return a content tree for the tree label */ - protected void printTreeHeading(String heading) { - h2(); - println(configuration.getText(heading)); - h2End(); - } - - /** - * Highlight "Tree" word in the navigation bar, since this is the tree page. - */ - protected void navLinkTree() { - navCellRevStart(); - fontStyle("NavBarFont1Rev"); - strongText("doclet.Tree"); - fontEnd(); - navCellEnd(); + protected Content getNavLinkTree() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, treeLabel); + return li; } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AllClassesFrameWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AllClassesFrameWriter.java index b62ec040b68..f25ff28e962 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AllClassesFrameWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AllClassesFrameWriter.java @@ -25,11 +25,14 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.util.*; -import com.sun.javadoc.*; import java.io.*; import java.util.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; + /** * Generate the file with list of all the classes in this run. This page will be * used in the left-hand bottom frame, when "All Classes" link is clicked in @@ -38,6 +41,7 @@ import java.util.*; * * @author Atul M Dambalkar * @author Doug Kramer + * @author Bhavesh Patel (Modified) */ public class AllClassesFrameWriter extends HtmlDocletWriter { @@ -56,6 +60,11 @@ public class AllClassesFrameWriter extends HtmlDocletWriter { */ protected IndexBuilder indexbuilder; + /** + * BR tag to be used within a document tree. + */ + final HtmlTree BR = new HtmlTree(HtmlTag.BR); + /** * Construct AllClassesFrameWriter object. Also initilises the indexbuilder * variable in this class. @@ -84,12 +93,12 @@ public class AllClassesFrameWriter extends HtmlDocletWriter { try { allclassgen = new AllClassesFrameWriter(configuration, filename, indexbuilder); - allclassgen.generateAllClassesFile(true); + allclassgen.buildAllClassesFile(true); allclassgen.close(); filename = OUTPUT_FILE_NAME_NOFRAMES; allclassgen = new AllClassesFrameWriter(configuration, filename, indexbuilder); - allclassgen.generateAllClassesFile(false); + allclassgen.buildAllClassesFile(false); allclassgen.close(); } catch (IOException exc) { configuration.standardmessage. @@ -100,30 +109,34 @@ public class AllClassesFrameWriter extends HtmlDocletWriter { } /** - * Print all the classes in table format in the file. + * Print all the classes in the file. * @param wantFrames True if we want frames. */ - protected void generateAllClassesFile(boolean wantFrames) throws IOException { + protected void buildAllClassesFile(boolean wantFrames) throws IOException { String label = configuration.getText("doclet.All_Classes"); - - printHtmlHeader(label, null, false); - - printAllClassesTableHeader(); - printAllClasses(wantFrames); - printAllClassesTableFooter(); - - printBodyHtmlEnd(); + Content body = getBody(false, getWindowTitle(label)); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, + HtmlStyle.bar, allclassesLabel); + body.addContent(heading); + Content ul = new HtmlTree(HtmlTag.UL); + // Generate the class links and add it to the tdFont tree. + addAllClasses(ul, wantFrames); + Content div = HtmlTree.DIV(HtmlStyle.indexContainer, ul); + body.addContent(div); + printHtmlDocument(null, false, body); } /** - * Use the sorted index of all the classes and print all the classes. + * Use the sorted index of all the classes and add all the classes to the + * content list. * + * @param content HtmlTree content to which all classes information will be added * @param wantFrames True if we want frames. */ - protected void printAllClasses(boolean wantFrames) { + protected void addAllClasses(Content content, boolean wantFrames) { for (int i = 0; i < indexbuilder.elements().length; i++) { Character unicode = (Character)((indexbuilder.elements())[i]); - generateContents(indexbuilder.getMemberList(unicode), wantFrames); + addContents(indexbuilder.getMemberList(unicode), wantFrames, content); } } @@ -136,46 +149,25 @@ public class AllClassesFrameWriter extends HtmlDocletWriter { * * @param classlist Sorted list of classes. * @param wantFrames True if we want frames. + * @param content HtmlTree content to which the links will be added */ - protected void generateContents(List classlist, boolean wantFrames) { + protected void addContents(List classlist, boolean wantFrames, + Content content) { for (int i = 0; i < classlist.size(); i++) { ClassDoc cd = (ClassDoc)classlist.get(i); if (!Util.isCoreClass(cd)) { continue; } String label = italicsClassName(cd, false); + Content linkContent; if(wantFrames){ - printLink(new LinkInfoImpl(LinkInfoImpl.ALL_CLASSES_FRAME, cd, - label, "classFrame") - ); + linkContent = new RawHtml(getLink(new LinkInfoImpl( + LinkInfoImpl.ALL_CLASSES_FRAME, cd, label, "classFrame"))); } else { - printLink(new LinkInfoImpl(cd, label)); + linkContent = new RawHtml(getLink(new LinkInfoImpl(cd, label))); } - br(); + Content li = HtmlTree.LI(linkContent); + content.addContent(li); } } - - /** - * Print the heading "All Classes" and also print Html table tag. - */ - protected void printAllClassesTableHeader() { - fontSizeStyle("+1", "FrameHeadingFont"); - strongText("doclet.All_Classes"); - fontEnd(); - br(); - table(); - tr(); - tdNowrap(); - fontStyle("FrameItemFont"); - } - - /** - * Print Html closing table tag. - */ - protected void printAllClassesTableFooter() { - fontEnd(); - tdEnd(); - trEnd(); - tableEnd(); - } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java index adc09a98734..714909c9a34 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java @@ -28,6 +28,7 @@ package com.sun.tools.doclets.formats.html; import java.io.*; import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; import com.sun.tools.doclets.internal.toolkit.*; /** @@ -54,29 +55,26 @@ public class AnnotationTypeOptionalMemberWriterImpl extends /** * {@inheritDoc} */ - public void writeMemberSummaryHeader(ClassDoc classDoc) { - writer.println(""); - writer.println(); - writer.printSummaryHeader(this, classDoc); + public Content getMemberSummaryHeader(ClassDoc classDoc, + Content memberSummaryTree) { + memberSummaryTree.addContent( + HtmlConstants.START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, classDoc, memberTree); + return memberTree; } /** * {@inheritDoc} */ - public void writeDefaultValueInfo(MemberDoc member) { + public void addDefaultValueInfo(MemberDoc member, Content annotationDocTree) { if (((AnnotationTypeElementDoc) member).defaultValue() != null) { - writer.printMemberDetailsListStartTag(); - writer.dd(); - writer.dl(); - writer.dt(); - writer.strong(ConfigurationImpl.getInstance(). - getText("doclet.Default")); - writer.dtEnd(); - writer.dd(); - writer.print(((AnnotationTypeElementDoc) member).defaultValue()); - writer.ddEnd(); - writer.dlEnd(); - writer.ddEnd(); + Content dt = HtmlTree.DT(writer.getResource("doclet.Default")); + Content dl = HtmlTree.DL(dt); + Content dd = HtmlTree.DD(new StringContent( + ((AnnotationTypeElementDoc) member).defaultValue().toString())); + dl.addContent(dd); + annotationDocTree.addContent(dl); } } @@ -90,45 +88,58 @@ public class AnnotationTypeOptionalMemberWriterImpl extends /** * {@inheritDoc} */ - public void printSummaryLabel() { - writer.printText("doclet.Annotation_Type_Optional_Member_Summary"); + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Annotation_Type_Optional_Member_Summary")); + memberTree.addContent(label); } /** * {@inheritDoc} */ - public void printTableSummary() { - writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + public String getTableSummary() { + return configuration().getText("doclet.Member_Table_Summary", configuration().getText("doclet.Annotation_Type_Optional_Member_Summary"), - configuration().getText("doclet.annotation_type_optional_members"))); + configuration().getText("doclet.annotation_type_optional_members")); } - public void printSummaryTableHeader(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + public String getCaption() { + return configuration().getText("doclet.Annotation_Type_Optional_Members"); + } + + /** + * {@inheritDoc} + */ + public String[] getSummaryTableHeader(ProgramElementDoc member) { String[] header = new String[] { writer.getModifierTypeHeader(), configuration().getText("doclet.0_and_1", configuration().getText("doclet.Annotation_Type_Optional_Member"), configuration().getText("doclet.Description")) }; - writer.summaryTableHeader(header, "col"); + return header; } /** * {@inheritDoc} */ - public void printSummaryAnchor(ClassDoc cd) { - writer.anchor("annotation_type_optional_element_summary"); + public void addSummaryAnchor(ClassDoc cd, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + "annotation_type_optional_element_summary")); } /** * {@inheritDoc} */ - protected void printNavSummaryLink(ClassDoc cd, boolean link) { + protected Content getNavSummaryLink(ClassDoc cd, boolean link) { if (link) { - writer.printHyperLink("", "annotation_type_optional_element_summary", - configuration().getText("doclet.navAnnotationTypeOptionalMember")); + return writer.getHyperLink("", "annotation_type_optional_element_summary", + writer.getResource("doclet.navAnnotationTypeOptionalMember")); } else { - writer.printText("doclet.navAnnotationTypeOptionalMember"); + return writer.getResource("doclet.navAnnotationTypeOptionalMember"); } } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java index ccfb05d90e8..7182eeceb0d 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java @@ -28,6 +28,7 @@ package com.sun.tools.doclets.formats.html; import java.io.*; import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; import com.sun.tools.doclets.internal.toolkit.*; /** @@ -51,122 +52,102 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter } /** - * Write the annotation type member summary header for the given class. - * - * @param classDoc the class the summary belongs to. + * {@inheritDoc} */ - public void writeMemberSummaryHeader(ClassDoc classDoc) { - writer.println(""); - writer.println(); - writer.printSummaryHeader(this, classDoc); - } - - /** - * Write the annotation type member summary footer for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeMemberSummaryFooter(ClassDoc classDoc) { - writer.printSummaryFooter(this, classDoc); + public Content getMemberSummaryHeader(ClassDoc classDoc, + Content memberSummaryTree) { + memberSummaryTree.addContent( + HtmlConstants.START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, classDoc, memberTree); + return memberTree; } /** * {@inheritDoc} */ - public void writeInheritedMemberSummaryHeader(ClassDoc classDoc) { - //Not appliable. - } - - /** - * {@inheritDoc} - */ - public void writeInheritedMemberSummary(ClassDoc classDoc, - ProgramElementDoc member, boolean isFirst, boolean isLast) { - //Not appliable. - } - - /** - * {@inheritDoc} - */ - public void writeInheritedMemberSummaryFooter(ClassDoc classDoc) { - //Not appliable. - } - - /** - * {@inheritDoc} - */ - public void writeHeader(ClassDoc classDoc, String header) { - writer.println(); - writer.println(""); - writer.println(); - writer.anchor("annotation_type_element_detail"); - writer.printTableHeadingBackground(header); - writer.println(); - } - - /** - * {@inheritDoc} - */ - public void writeMemberHeader(MemberDoc member, boolean isFirst) { - if (! isFirst) { - writer.printMemberHeader(); - writer.println(""); + public void addAnnotationDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree) { + if (!writer.printedAnnotationHeading) { + memberDetailsTree.addContent(writer.getMarkerAnchor( + "annotation_type_element_detail")); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.annotationTypeDetailsLabel); + memberDetailsTree.addContent(heading); + writer.printedAnnotationHeading = true; } - writer.anchor(member.name() + ((ExecutableMemberDoc) member).signature()); - writer.h3(); - writer.print(member.name()); - writer.h3End(); } /** * {@inheritDoc} */ - public void writeSignature(MemberDoc member) { - writer.pre(); - writer.writeAnnotationInfo(member); - printModifiers(member); - writer.printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, - getType(member))); - print(' '); + public Content getAnnotationDocTreeHeader(MemberDoc member, + Content annotationDetailsTree) { + annotationDetailsTree.addContent( + writer.getMarkerAnchor(member.name() + + ((ExecutableMemberDoc) member).signature())); + Content annotationDocTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(member.name()); + annotationDocTree.addContent(heading); + return annotationDocTree; + } + + /** + * {@inheritDoc} + */ + public Content getSignature(MemberDoc member) { + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(member, pre); + addModifiers(member, pre); + Content link = new RawHtml( + writer.getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, + getType(member)))); + pre.addContent(link); + pre.addContent(writer.getSpace()); if (configuration().linksource) { - writer.printSrcLink(member, member.name()); + Content memberName = new StringContent(member.name()); + writer.addSrcLink(member, memberName, pre); } else { - strong(member.name()); + addName(member.name(), pre); } - writer.preEnd(); - assert !writer.getMemberDetailsListPrinted(); + return pre; } /** * {@inheritDoc} */ - public void writeComments(MemberDoc member) { - printComment(member); + public void addDeprecated(MemberDoc member, Content annotationDocTree) { + addDeprecatedInfo(member, annotationDocTree); } /** - * Write the tag output for the given member. - * - * @param member the member being documented. + * {@inheritDoc} */ - public void writeTags(MemberDoc member) { - writer.printTags(member); + public void addComments(MemberDoc member, Content annotationDocTree) { + addComment(member, annotationDocTree); } /** - * Write the annotation type member footer. + * {@inheritDoc} */ - public void writeMemberFooter() { - printMemberFooter(); + public void addTags(MemberDoc member, Content annotationDocTree) { + writer.addTagsInfo(member, annotationDocTree); } /** - * Write the footer for the annotation type member documentation. - * - * @param classDoc the class that the annotation type member belong to. + * {@inheritDoc} */ - public void writeFooter(ClassDoc classDoc) { - //No footer to write for annotation type member documentation + public Content getAnnotationDetails(Content annotationDetailsTree) { + return getMemberTree(annotationDetailsTree); + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationDoc(Content annotationDocTree, + boolean isLastContent) { + return getMemberTree(annotationDocTree, isLastContent); } /** @@ -179,113 +160,120 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter /** * {@inheritDoc} */ - public void printSummaryLabel() { - writer.printText("doclet.Annotation_Type_Required_Member_Summary"); + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Annotation_Type_Required_Member_Summary")); + memberTree.addContent(label); } /** * {@inheritDoc} */ - public void printTableSummary() { - writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + public String getTableSummary() { + return configuration().getText("doclet.Member_Table_Summary", configuration().getText("doclet.Annotation_Type_Required_Member_Summary"), - configuration().getText("doclet.annotation_type_required_members"))); + configuration().getText("doclet.annotation_type_required_members")); } - public void printSummaryTableHeader(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + public String getCaption() { + return configuration().getText("doclet.Annotation_Type_Required_Members"); + } + + /** + * {@inheritDoc} + */ + public String[] getSummaryTableHeader(ProgramElementDoc member) { String[] header = new String[] { writer.getModifierTypeHeader(), configuration().getText("doclet.0_and_1", configuration().getText("doclet.Annotation_Type_Required_Member"), configuration().getText("doclet.Description")) }; - writer.summaryTableHeader(header, "col"); + return header; } /** * {@inheritDoc} */ - public void printSummaryAnchor(ClassDoc cd) { - writer.anchor("annotation_type_required_element_summary"); + public void addSummaryAnchor(ClassDoc cd, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + "annotation_type_required_element_summary")); } /** * {@inheritDoc} */ - public void printInheritedSummaryAnchor(ClassDoc cd) { - } // no such - - /** - * {@inheritDoc} - */ - public void printInheritedSummaryLabel(ClassDoc cd) { - // no such + public void addInheritedSummaryAnchor(ClassDoc cd, Content inheritedTree) { } /** * {@inheritDoc} */ - protected void writeSummaryLink(int context, ClassDoc cd, ProgramElementDoc member) { - writer.strong(); - writer.printDocLink(context, (MemberDoc) member, member.name(), false); - writer.strongEnd(); + public void addInheritedSummaryLabel(ClassDoc cd, Content inheritedTree) { } /** * {@inheritDoc} */ - protected void writeInheritedSummaryLink(ClassDoc cd, - ProgramElementDoc member) { + protected void addSummaryLink(int context, ClassDoc cd, ProgramElementDoc member, + Content tdSummary) { + Content strong = HtmlTree.STRONG(new RawHtml( + writer.getDocLink(context, (MemberDoc) member, member.name(), false))); + Content code = HtmlTree.CODE(strong); + tdSummary.addContent(code); + } + + /** + * {@inheritDoc} + */ + protected void addInheritedSummaryLink(ClassDoc cd, + ProgramElementDoc member, Content linksTree) { //Not applicable. } /** * {@inheritDoc} */ - protected void printSummaryType(ProgramElementDoc member) { + protected void addSummaryType(ProgramElementDoc member, Content tdSummaryType) { MemberDoc m = (MemberDoc)member; - printModifierAndType(m, getType(m)); + addModifierAndType(m, getType(m), tdSummaryType); } /** * {@inheritDoc} */ - protected void writeDeprecatedLink(ProgramElementDoc member) { - writer.printDocLink(LinkInfoImpl.CONTEXT_MEMBER, - (MemberDoc) member, ((MemberDoc)member).qualifiedName(), false); + protected Content getDeprecatedLink(ProgramElementDoc member) { + return writer.getDocLink(LinkInfoImpl.CONTEXT_MEMBER, + (MemberDoc) member, ((MemberDoc)member).qualifiedName()); } /** * {@inheritDoc} */ - protected void printNavSummaryLink(ClassDoc cd, boolean link) { + protected Content getNavSummaryLink(ClassDoc cd, boolean link) { if (link) { - writer.printHyperLink("", "annotation_type_required_element_summary", - configuration().getText("doclet.navAnnotationTypeRequiredMember")); + return writer.getHyperLink("", "annotation_type_required_element_summary", + writer.getResource("doclet.navAnnotationTypeRequiredMember")); } else { - writer.printText("doclet.navAnnotationTypeRequiredMember"); + return writer.getResource("doclet.navAnnotationTypeRequiredMember"); } } /** * {@inheritDoc} */ - protected void printNavDetailLink(boolean link) { + protected void addNavDetailLink(boolean link, Content liNav) { if (link) { - writer.printHyperLink("", "annotation_type_element_detail", - configuration().getText("doclet.navAnnotationTypeMember")); + liNav.addContent(writer.getHyperLink("", "annotation_type_element_detail", + writer.getResource("doclet.navAnnotationTypeMember"))); } else { - writer.printText("doclet.navAnnotationTypeMember"); + liNav.addContent(writer.getResource("doclet.navAnnotationTypeMember")); } } - /** - * {@inheritDoc} - */ - public void writeDeprecated(MemberDoc member) { - printDeprecated(member); - } - private Type getType(MemberDoc member) { if (member instanceof FieldDoc) { return ((FieldDoc) member).type(); diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java index 1393aeb4cec..b32b04e0749 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java @@ -29,6 +29,7 @@ import com.sun.javadoc.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.builders.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Generate the Class Information Page. @@ -40,6 +41,7 @@ import com.sun.tools.doclets.internal.toolkit.builders.*; * * @author Atul M Dambalkar * @author Robert Field + * @author Bhavesh Patel (Modified) */ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter implements AnnotationTypeWriter { @@ -69,126 +71,168 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter } /** - * Print this package link + * Get this package link. + * + * @return a content tree for the package link */ - protected void navLinkPackage() { - navCellStart(); - printHyperLink("package-summary.html", "", - configuration.getText("doclet.Package"), true, "NavBarFont1"); - navCellEnd(); + protected Content getNavLinkPackage() { + Content linkContent = getHyperLink("package-summary.html", "", + packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; } /** - * Print class page indicator + * Get the class link. + * + * @return a content tree for the class link */ - protected void navLinkClass() { - navCellRevStart(); - fontStyle("NavBarFont1Rev"); - strongText("doclet.Class"); - fontEnd(); - navCellEnd(); + protected Content getNavLinkClass() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, classLabel); + return li; } /** - * Print class use link + * Get the class use link. + * + * @return a content tree for the class use link */ - protected void navLinkClassUse() { - navCellStart(); - printHyperLink("class-use/" + filename, "", - configuration.getText("doclet.navClassUse"), true, "NavBarFont1"); - navCellEnd(); + protected Content getNavLinkClassUse() { + Content linkContent = getHyperLink("class-use/" + filename, "", useLabel); + Content li = HtmlTree.LI(linkContent); + return li; } /** - * Print previous package link + * Get link to previous class. + * + * @return a content tree for the previous class link */ - protected void navLinkPrevious() { - if (prev == null) { - printText("doclet.Prev_Class"); - } else { - printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS, - prev.asClassDoc(), "", - configuration.getText("doclet.Prev_Class"), true)); + public Content getNavLinkPrevious() { + Content li; + if (prev != null) { + Content prevLink = new RawHtml(getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_CLASS, prev.asClassDoc(), "", + configuration.getText("doclet.Prev_Class"), true))); + li = HtmlTree.LI(prevLink); } + else + li = HtmlTree.LI(prevclassLabel); + return li; } /** - * Print next package link + * Get link to next class. + * + * @return a content tree for the next class link */ - protected void navLinkNext() { - if (next == null) { - printText("doclet.Next_Class"); - } else { - printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS, - next.asClassDoc(), "", - configuration.getText("doclet.Next_Class"), true)); + public Content getNavLinkNext() { + Content li; + if (next != null) { + Content nextLink = new RawHtml(getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_CLASS, next.asClassDoc(), "", + configuration.getText("doclet.Next_Class"), true))); + li = HtmlTree.LI(nextLink); } + else + li = HtmlTree.LI(nextclassLabel); + return li; } /** * {@inheritDoc} */ - public void writeHeader(String header) { - + public Content getHeader(String header) { String pkgname = (annotationType.containingPackage() != null)? annotationType.containingPackage().name(): ""; String clname = annotationType.name(); - - printHtmlHeader(clname, - configuration.metakeywords.getMetaKeywords(annotationType), true); - printTop(); - navLinks(true); - hr(); - println(""); - h2(); + Content bodyTree = getBody(true, getWindowTitle(clname)); + addTop(bodyTree); + addNavLinks(true, bodyTree); + bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.header); if (pkgname.length() > 0) { - font("-1"); print(pkgname); fontEnd(); br(); + Content pkgNameContent = new StringContent(pkgname); + Content pkgNamePara = HtmlTree.P(HtmlStyle.subTitle, pkgNameContent); + div.addContent(pkgNamePara); } - print(header + getTypeParameterLinks(new LinkInfoImpl( - LinkInfoImpl.CONTEXT_CLASS_HEADER, - annotationType, false))); - h2End(); + LinkInfoImpl linkInfo = new LinkInfoImpl( + LinkInfoImpl.CONTEXT_CLASS_HEADER, annotationType, false); + Content headerContent = new StringContent(header); + Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, true, + HtmlStyle.title, headerContent); + heading.addContent(new RawHtml(getTypeParameterLinks(linkInfo))); + div.addContent(heading); + bodyTree.addContent(div); + return bodyTree; } /** * {@inheritDoc} */ - public void writeFooter() { - println(""); - hr(); - navLinks(false); - printBottom(); - printBodyHtmlEnd(); + public Content getAnnotationContentHeader() { + return getContentHeader(); } /** * {@inheritDoc} */ - public void writeAnnotationTypeSignature(String modifiers) { - preNoNewLine(); - writeAnnotationInfo(annotationType); - print(modifiers); - String name = annotationType.name() + - getTypeParameterLinks(new LinkInfoImpl( - LinkInfoImpl.CONTEXT_CLASS_SIGNATURE, annotationType, false)); + public void addFooter(Content contentTree) { + contentTree.addContent(HtmlConstants.END_OF_CLASS_DATA); + addNavLinks(false, contentTree); + addBottom(contentTree); + } + + /** + * {@inheritDoc} + */ + public void printDocument(Content contentTree) { + printHtmlDocument(configuration.metakeywords.getMetaKeywords(annotationType), + true, contentTree); + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationInfoTreeHeader() { + return getMemberTreeHeader(); + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationInfo(Content annotationInfoTree) { + return getMemberTree(HtmlStyle.description, annotationInfoTree); + } + + /** + * {@inheritDoc} + */ + public void addAnnotationTypeSignature(String modifiers, Content annotationInfoTree) { + annotationInfoTree.addContent(new HtmlTree(HtmlTag.BR)); + Content pre = new HtmlTree(HtmlTag.PRE); + addAnnotationInfo(annotationType, pre); + pre.addContent(modifiers); + LinkInfoImpl linkInfo = new LinkInfoImpl( + LinkInfoImpl.CONTEXT_CLASS_SIGNATURE, annotationType, false); + Content name = new RawHtml (annotationType.name() + + getTypeParameterLinks(linkInfo)); if (configuration().linksource) { - printSrcLink(annotationType, name); + addSrcLink(annotationType, name, pre); } else { - strong(name); + pre.addContent(HtmlTree.STRONG(name)); } - preEnd(); - p(); + annotationInfoTree.addContent(pre); } /** * {@inheritDoc} */ - public void writeAnnotationTypeDescription() { + public void addAnnotationTypeDescription(Content annotationInfoTree) { if(!configuration.nocomment) { - // generate documentation for the class. if (annotationType.inlineTags().length > 0) { - printInlineComment(annotationType); - p(); + addInlineComment(annotationType, annotationInfoTree); } } } @@ -196,148 +240,152 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter /** * {@inheritDoc} */ - public void writeAnnotationTypeTagInfo() { - boolean needHr = annotationType.elements().length > 0; + public void addAnnotationTypeTagInfo(Content annotationInfoTree) { if(!configuration.nocomment) { - // Print Information about all the tags here - printTags(annotationType); - if (needHr) { - hr(); - } - p(); - } else if (needHr) { - hr(); + addTagsInfo(annotationType, annotationInfoTree); } } /** * {@inheritDoc} */ - public void writeAnnotationTypeDeprecationInfo() { - hr(); + public void addAnnotationTypeDeprecationInfo(Content annotationInfoTree) { + Content hr = new HtmlTree(HtmlTag.HR); + annotationInfoTree.addContent(hr); Tag[] deprs = annotationType.tags("deprecated"); if (Util.isDeprecated(annotationType)) { - strongText("doclet.Deprecated"); + Content strong = HtmlTree.STRONG(deprecatedPhrase); + Content div = HtmlTree.DIV(HtmlStyle.block, strong); if (deprs.length > 0) { Tag[] commentTags = deprs[0].inlineTags(); if (commentTags.length > 0) { - - space(); - printInlineDeprecatedComment(annotationType, deprs[0]); + div.addContent(getSpace()); + addInlineDeprecatedComment(annotationType, deprs[0], div); } } - p(); + annotationInfoTree.addContent(div); } } - protected void navLinkTree() { - navCellStart(); - printHyperLink("package-tree.html", "", - configuration.getText("doclet.Tree"), true, "NavBarFont1"); - navCellEnd(); + /** + * {@inheritDoc} + */ + public void addAnnotationDetailsMarker(Content memberDetails) { + memberDetails.addContent(HtmlConstants.START_OF_ANNOTATION_TYPE_DETAILS); } - protected void printSummaryDetailLinks() { - try { - tr(); - tdVAlignClass("top", "NavBarCell3"); - font("-2"); - print(" "); - navSummaryLinks(); - fontEnd(); - tdEnd(); + /** + * {@inheritDoc} + */ + protected Content getNavLinkTree() { + Content treeLinkContent = getHyperLink("package-tree.html", + "", treeLabel, "", ""); + Content li = HtmlTree.LI(treeLinkContent); + return li; + } - tdVAlignClass("top", "NavBarCell3"); - font("-2"); - navDetailLinks(); - fontEnd(); - tdEnd(); - trEnd(); + /** + * Add summary details to the navigation bar. + * + * @param subDiv the content tree to which the summary detail links will be added + */ + protected void addSummaryDetailLinks(Content subDiv) { + try { + Content div = HtmlTree.DIV(getNavSummaryLinks()); + div.addContent(getNavDetailLinks()); + subDiv.addContent(div); } catch (Exception e) { e.printStackTrace(); throw new DocletAbortException(); } } - protected void navSummaryLinks() throws Exception { - printText("doclet.Summary"); - space(); + /** + * Get summary links for navigation bar. + * + * @return the content tree for the navigation summary links + */ + protected Content getNavSummaryLinks() throws Exception { + Content li = HtmlTree.LI(summaryLabel); + li.addContent(getSpace()); + Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) - configuration.getBuilderFactory().getMemberSummaryBuilder(this); - writeNavSummaryLink(memberSummaryBuilder, - "doclet.navAnnotationTypeRequiredMember", - VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED); - navGap(); - writeNavSummaryLink(memberSummaryBuilder, - "doclet.navAnnotationTypeOptionalMember", - VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL); + configuration.getBuilderFactory().getMemberSummaryBuilder(this); + Content liNavReq = new HtmlTree(HtmlTag.LI); + addNavSummaryLink(memberSummaryBuilder, + "doclet.navAnnotationTypeRequiredMember", + VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED, liNavReq); + addNavGap(liNavReq); + ulNav.addContent(liNavReq); + Content liNavOpt = new HtmlTree(HtmlTag.LI); + addNavSummaryLink(memberSummaryBuilder, + "doclet.navAnnotationTypeOptionalMember", + VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL, liNavOpt); + ulNav.addContent(liNavOpt); + return ulNav; } - private void writeNavSummaryLink(MemberSummaryBuilder builder, - String label, int type) { + /** + * Add the navigation summary link. + * + * @param builder builder for the member to be documented + * @param label the label for the navigation + * @param type type to be documented + * @param liNav the content tree to which the navigation summary link will be added + */ + protected void addNavSummaryLink(MemberSummaryBuilder builder, + String label, int type, Content liNav) { AbstractMemberWriter writer = ((AbstractMemberWriter) builder. - getMemberSummaryWriter(type)); + getMemberSummaryWriter(type)); if (writer == null) { - printText(label); + liNav.addContent(getResource(label)); } else { - writer.printNavSummaryLink(null, - ! builder.getVisibleMemberMap(type).noVisibleMembers()); + liNav.addContent(writer.getNavSummaryLink(null, + ! builder.getVisibleMemberMap(type).noVisibleMembers())); } } /** - * Method navDetailLinks - * - * @throws Exception + * Get detail links for the navigation bar. * + * @return the content tree for the detail links */ - protected void navDetailLinks() throws Exception { - printText("doclet.Detail"); - space(); + protected Content getNavDetailLinks() throws Exception { + Content li = HtmlTree.LI(detailLabel); + li.addContent(getSpace()); + Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) - configuration.getBuilderFactory().getMemberSummaryBuilder(this); + configuration.getBuilderFactory().getMemberSummaryBuilder(this); AbstractMemberWriter writerOptional = - ((AbstractMemberWriter) memberSummaryBuilder. + ((AbstractMemberWriter) memberSummaryBuilder. getMemberSummaryWriter(VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL)); AbstractMemberWriter writerRequired = - ((AbstractMemberWriter) memberSummaryBuilder. + ((AbstractMemberWriter) memberSummaryBuilder. getMemberSummaryWriter(VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED)); if (writerOptional != null){ - writerOptional.printNavDetailLink(annotationType.elements().length > 0); + Content liNavOpt = new HtmlTree(HtmlTag.LI); + writerOptional.addNavDetailLink(annotationType.elements().length > 0, liNavOpt); + ulNav.addContent(liNavOpt); } else if (writerRequired != null){ - writerRequired.printNavDetailLink(annotationType.elements().length > 0); + Content liNavReq = new HtmlTree(HtmlTag.LI); + writerRequired.addNavDetailLink(annotationType.elements().length > 0, liNavReq); + ulNav.addContent(liNavReq); } else { - printText("doclet.navAnnotationTypeMember"); + Content liNav = HtmlTree.LI(getResource("doclet.navAnnotationTypeMember")); + ulNav.addContent(liNav); } - } - - protected void navGap() { - space(); - print('|'); - space(); + return ulNav; } /** - * If this is an inner class or interface, write the enclosing class or - * interface. + * Add gap between navigation bar elements. + * + * @param liNav the content tree to which the gap will be added */ - public void writeNestedClassInfo() { - ClassDoc outerClass = annotationType.containingClass(); - if (outerClass != null) { - dl(); - dt(); - if (annotationType.isInterface()) { - strongText("doclet.Enclosing_Interface"); - } else { - strongText("doclet.Enclosing_Class"); - } - dtEnd(); - dd(); - printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS, outerClass, - false)); - ddEnd(); - dlEnd(); - } + protected void addNavGap(Content liNav) { + liNav.addContent(getSpace()); + liNav.addContent("|"); + liNav.addContent(getSpace()); } /** @@ -346,11 +394,4 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter public AnnotationTypeDoc getAnnotationTypeDoc() { return annotationType; } - - /** - * {@inheritDoc} - */ - public void completeMemberSummaryBuild() { - p(); - } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java index 511b3d59919..ed1c16153a5 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java @@ -25,10 +25,12 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.util.*; -import com.sun.javadoc.*; import java.io.*; import java.util.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; /** * Generate class usage information. @@ -207,257 +209,301 @@ public class ClassUseWriter extends SubWriterHolderWriter { } /** - * Print the class use list. + * Generate the class use list. */ protected void generateClassUseFile() throws IOException { - - printClassUseHeader(); - + Content body = getClassUseHeader(); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.classUseContainer); if (pkgSet.size() > 0) { - generateClassUse(); + addClassUse(div); } else { - printText("doclet.ClassUse_No.usage.of.0", - classdoc.qualifiedName()); - p(); + div.addContent(getResource("doclet.ClassUse_No.usage.of.0", + classdoc.qualifiedName())); } - - printClassUseFooter(); + body.addContent(div); + addNavLinks(false, body); + addBottom(body); + printHtmlDocument(null, true, body); } - protected void generateClassUse() throws IOException { + /** + * Add the class use documentation. + * + * @param contentTree the content tree to which the class use information will be added + */ + protected void addClassUse(Content contentTree) throws IOException { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); if (configuration.packages.length > 1) { - generatePackageList(); - generatePackageAnnotationList(); + addPackageList(ul); + addPackageAnnotationList(ul); } - generateClassList(); + addClassList(ul); + contentTree.addContent(ul); } - protected void generatePackageList() throws IOException { - tableIndexSummary(useTableSummary); - tableCaptionStart(); - printText("doclet.ClassUse_Packages.that.use.0", - getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, - false))); - tableCaptionEnd(); - summaryTableHeader(packageTableHeader, "col"); - - for (Iterator it = pkgSet.iterator(); it.hasNext();) { + /** + * Add the packages list that use the given class. + * + * @param contentTree the content tree to which the packages list will be added + */ + protected void addPackageList(Content contentTree) throws IOException { + Content table = HtmlTree.TABLE(0, 3, 0, useTableSummary, + getTableCaption(configuration().getText( + "doclet.ClassUse_Packages.that.use.0", + getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, + false))))); + table.addContent(getSummaryTableHeader(packageTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + Iterator it = pkgSet.iterator(); + for (int i = 0; it.hasNext(); i++) { PackageDoc pkg = it.next(); - generatePackageUse(pkg); + HtmlTree tr = new HtmlTree(HtmlTag.TR); + if (i % 2 == 0) { + tr.addStyle(HtmlStyle.altColor); + } else { + tr.addStyle(HtmlStyle.rowColor); + } + addPackageUse(pkg, tr); + tbody.addContent(tr); } - tableEnd(); - space(); - p(); + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + contentTree.addContent(li); } - protected void generatePackageAnnotationList() throws IOException { - if ((! classdoc.isAnnotationType()) || - pkgToPackageAnnotations == null || - pkgToPackageAnnotations.size() == 0) + /** + * Add the package annotation list. + * + * @param contentTree the content tree to which the package annotation list will be added + */ + protected void addPackageAnnotationList(Content contentTree) throws IOException { + if ((!classdoc.isAnnotationType()) || + pkgToPackageAnnotations == null || + pkgToPackageAnnotations.size() == 0) { return; - tableIndexSummary(useTableSummary); - tableCaptionStart(); - printText("doclet.ClassUse_PackageAnnotation", - getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, - false))); - tableCaptionEnd(); - summaryTableHeader(packageTableHeader, "col"); - for (Iterator it = pkgToPackageAnnotations.iterator(); it.hasNext();) { - PackageDoc pkg = it.next(); - trBgcolorStyle("white", "TableRowColor"); - summaryRow(0); - //Just want an anchor here. - printPackageLink(pkg, pkg.name(), true); - summaryRowEnd(); - summaryRow(0); - printSummaryComment(pkg); - space(); - summaryRowEnd(); - trEnd(); } - tableEnd(); - space(); - p(); + Content table = HtmlTree.TABLE(0, 3, 0, useTableSummary, + getTableCaption(configuration().getText( + "doclet.ClassUse_PackageAnnotation", + getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, + false))))); + table.addContent(getSummaryTableHeader(packageTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + Iterator it = pkgToPackageAnnotations.iterator(); + for (int i = 0; it.hasNext(); i++) { + PackageDoc pkg = it.next(); + HtmlTree tr = new HtmlTree(HtmlTag.TR); + if (i % 2 == 0) { + tr.addStyle(HtmlStyle.altColor); + } else { + tr.addStyle(HtmlStyle.rowColor); + } + Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, + getPackageLink(pkg, new StringContent(pkg.name()))); + tr.addContent(tdFirst); + HtmlTree tdLast = new HtmlTree(HtmlTag.TD); + tdLast.addStyle(HtmlStyle.colLast); + if (pkg != null) { + addSummaryComment(pkg, tdLast); + } else { + tdLast.addContent(getSpace()); + } + tr.addContent(tdLast); + tbody.addContent(tr); + } + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + contentTree.addContent(li); } - protected void generateClassList() throws IOException { + /** + * Add the class list that use the given class. + * + * @param contentTree the content tree to which the class list will be added + */ + protected void addClassList(Content contentTree) throws IOException { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); for (Iterator it = pkgSet.iterator(); it.hasNext();) { PackageDoc pkg = it.next(); - anchor(pkg.name()); - tableIndexSummary(); - tableHeaderStart("#CCCCFF"); - printText("doclet.ClassUse_Uses.of.0.in.1", - getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, + Content li = HtmlTree.LI(HtmlStyle.blockList, getMarkerAnchor(pkg.name())); + Content link = new RawHtml( + configuration.getText("doclet.ClassUse_Uses.of.0.in.1", + getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, false)), - getPackageLink(pkg, Util.getPackageName(pkg), false)); - tableHeaderEnd(); - tableEnd(); - space(); - p(); - generateClassUse(pkg); + getPackageLinkString(pkg, Util.getPackageName(pkg), false))); + Content heading = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, link); + li.addContent(heading); + addClassUse(pkg, li); + ul.addContent(li); } + Content li = HtmlTree.LI(HtmlStyle.blockList, ul); + contentTree.addContent(li); } /** - * Print the package use list. + * Add the package use information. + * + * @param pkg the package that uses the given class + * @param contentTree the content tree to which the package use information will be added */ - protected void generatePackageUse(PackageDoc pkg) throws IOException { - trBgcolorStyle("white", "TableRowColor"); - summaryRow(0); - //Just want an anchor here. - printHyperLink("", pkg.name(), Util.getPackageName(pkg), true); - summaryRowEnd(); - summaryRow(0); - printSummaryComment(pkg); - space(); - summaryRowEnd(); - trEnd(); + protected void addPackageUse(PackageDoc pkg, Content contentTree) throws IOException { + Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, + getHyperLink("", pkg.name(), new StringContent(Util.getPackageName(pkg)))); + contentTree.addContent(tdFirst); + HtmlTree tdLast = new HtmlTree(HtmlTag.TD); + tdLast.addStyle(HtmlStyle.colLast); + if (pkg != null) + addSummaryComment(pkg, tdLast); + else + tdLast.addContent(getSpace()); + contentTree.addContent(tdLast); } /** - * Print the class use list. + * Add the class use information. + * + * @param pkg the package that uses the given class + * @param contentTree the content tree to which the class use information will be added */ - protected void generateClassUse(PackageDoc pkg) throws IOException { + protected void addClassUse(PackageDoc pkg, Content contentTree) throws IOException { String classLink = getLink(new LinkInfoImpl( LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, false)); - String pkgLink = getPackageLink(pkg, Util.getPackageName(pkg), false); - classSubWriter.printUseInfo(pkgToClassAnnotations.get(pkg.name()), + String pkgLink = getPackageLinkString(pkg, Util.getPackageName(pkg), false); + classSubWriter.addUseInfo(pkgToClassAnnotations.get(pkg.name()), configuration.getText("doclet.ClassUse_Annotation", classLink, - pkgLink), classUseTableSummary); - classSubWriter.printUseInfo(pkgToClassTypeParameter.get(pkg.name()), + pkgLink), classUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToClassTypeParameter.get(pkg.name()), configuration.getText("doclet.ClassUse_TypeParameter", classLink, - pkgLink), classUseTableSummary); - classSubWriter.printUseInfo(pkgToSubclass.get(pkg.name()), + pkgLink), classUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToSubclass.get(pkg.name()), configuration.getText("doclet.ClassUse_Subclass", classLink, - pkgLink), subclassUseTableSummary); - classSubWriter.printUseInfo(pkgToSubinterface.get(pkg.name()), + pkgLink), subclassUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToSubinterface.get(pkg.name()), configuration.getText("doclet.ClassUse_Subinterface", classLink, - pkgLink), subinterfaceUseTableSummary); - classSubWriter.printUseInfo(pkgToImplementingClass.get(pkg.name()), + pkgLink), subinterfaceUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToImplementingClass.get(pkg.name()), configuration.getText("doclet.ClassUse_ImplementingClass", classLink, - pkgLink), classUseTableSummary); - fieldSubWriter.printUseInfo(pkgToField.get(pkg.name()), + pkgLink), classUseTableSummary, contentTree); + fieldSubWriter.addUseInfo(pkgToField.get(pkg.name()), configuration.getText("doclet.ClassUse_Field", classLink, - pkgLink), fieldUseTableSummary); - fieldSubWriter.printUseInfo(pkgToFieldAnnotations.get(pkg.name()), + pkgLink), fieldUseTableSummary, contentTree); + fieldSubWriter.addUseInfo(pkgToFieldAnnotations.get(pkg.name()), configuration.getText("doclet.ClassUse_FieldAnnotations", classLink, - pkgLink), fieldUseTableSummary); - fieldSubWriter.printUseInfo(pkgToFieldTypeParameter.get(pkg.name()), + pkgLink), fieldUseTableSummary, contentTree); + fieldSubWriter.addUseInfo(pkgToFieldTypeParameter.get(pkg.name()), configuration.getText("doclet.ClassUse_FieldTypeParameter", classLink, - pkgLink), fieldUseTableSummary); - methodSubWriter.printUseInfo(pkgToMethodAnnotations.get(pkg.name()), + pkgLink), fieldUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodAnnotations.get(pkg.name()), configuration.getText("doclet.ClassUse_MethodAnnotations", classLink, - pkgLink), methodUseTableSummary); - methodSubWriter.printUseInfo(pkgToMethodParameterAnnotations.get(pkg.name()), + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodParameterAnnotations.get(pkg.name()), configuration.getText("doclet.ClassUse_MethodParameterAnnotations", classLink, - pkgLink), methodUseTableSummary); - methodSubWriter.printUseInfo(pkgToMethodTypeParameter.get(pkg.name()), + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodTypeParameter.get(pkg.name()), configuration.getText("doclet.ClassUse_MethodTypeParameter", classLink, - pkgLink), methodUseTableSummary); - methodSubWriter.printUseInfo(pkgToMethodReturn.get(pkg.name()), + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodReturn.get(pkg.name()), configuration.getText("doclet.ClassUse_MethodReturn", classLink, - pkgLink), methodUseTableSummary); - methodSubWriter.printUseInfo(pkgToMethodReturnTypeParameter.get(pkg.name()), + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodReturnTypeParameter.get(pkg.name()), configuration.getText("doclet.ClassUse_MethodReturnTypeParameter", classLink, - pkgLink), methodUseTableSummary); - methodSubWriter.printUseInfo(pkgToMethodArgs.get(pkg.name()), + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodArgs.get(pkg.name()), configuration.getText("doclet.ClassUse_MethodArgs", classLink, - pkgLink), methodUseTableSummary); - methodSubWriter.printUseInfo(pkgToMethodArgTypeParameter.get(pkg.name()), + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodArgTypeParameter.get(pkg.name()), configuration.getText("doclet.ClassUse_MethodArgsTypeParameters", classLink, - pkgLink), methodUseTableSummary); - methodSubWriter.printUseInfo(pkgToMethodThrows.get(pkg.name()), + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodThrows.get(pkg.name()), configuration.getText("doclet.ClassUse_MethodThrows", classLink, - pkgLink), methodUseTableSummary); - constrSubWriter.printUseInfo(pkgToConstructorAnnotations.get(pkg.name()), + pkgLink), methodUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorAnnotations.get(pkg.name()), configuration.getText("doclet.ClassUse_ConstructorAnnotations", classLink, - pkgLink), constructorUseTableSummary); - constrSubWriter.printUseInfo(pkgToConstructorParameterAnnotations.get(pkg.name()), + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorParameterAnnotations.get(pkg.name()), configuration.getText("doclet.ClassUse_ConstructorParameterAnnotations", classLink, - pkgLink), constructorUseTableSummary); - constrSubWriter.printUseInfo(pkgToConstructorArgs.get(pkg.name()), + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorArgs.get(pkg.name()), configuration.getText("doclet.ClassUse_ConstructorArgs", classLink, - pkgLink), constructorUseTableSummary); - constrSubWriter.printUseInfo(pkgToConstructorArgTypeParameter.get(pkg.name()), + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorArgTypeParameter.get(pkg.name()), configuration.getText("doclet.ClassUse_ConstructorArgsTypeParameters", classLink, - pkgLink), constructorUseTableSummary); - constrSubWriter.printUseInfo(pkgToConstructorThrows.get(pkg.name()), + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorThrows.get(pkg.name()), configuration.getText("doclet.ClassUse_ConstructorThrows", classLink, - pkgLink), constructorUseTableSummary); + pkgLink), constructorUseTableSummary, contentTree); } /** - * Print the header for the class use Listing. + * Get the header for the class use Listing. + * + * @return a content tree representing the class use header */ - protected void printClassUseHeader() { + protected Content getClassUseHeader() { String cltype = configuration.getText(classdoc.isInterface()? - "doclet.Interface": - "doclet.Class"); + "doclet.Interface":"doclet.Class"); String clname = classdoc.qualifiedName(); - printHtmlHeader(configuration.getText("doclet.Window_ClassUse_Header", - cltype, clname), null, true); - printTop(); - navLinks(true); - hr(); - center(); - h2(); - strongText("doclet.ClassUse_Title", cltype, clname); - h2End(); - centerEnd(); + String title = configuration.getText("doclet.Window_ClassUse_Header", + cltype, clname); + Content bodyTree = getBody(true, getWindowTitle(title)); + addTop(bodyTree); + addNavLinks(true, bodyTree); + Content headContent = getResource("doclet.ClassUse_Title", cltype, clname); + Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, + true, HtmlStyle.title, headContent); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + bodyTree.addContent(div); + return bodyTree; } /** - * Print the footer for the class use Listing. + * Get this package link. + * + * @return a content tree for the package link */ - protected void printClassUseFooter() { - hr(); - navLinks(false); - printBottom(); - printBodyHtmlEnd(); - } - - - /** - * Print this package link - */ - protected void navLinkPackage() { - navCellStart(); - printHyperLink("../package-summary.html", "", - configuration.getText("doclet.Package"), true, "NavBarFont1"); - navCellEnd(); + protected Content getNavLinkPackage() { + Content linkContent = getHyperLink("../package-summary.html", "", + packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; } /** - * Print class page indicator + * Get class page link. + * + * @return a content tree for the class page link */ - protected void navLinkClass() { - navCellStart(); - printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, "", - configuration.getText("doclet.Class"), true, "NavBarFont1")); - navCellEnd(); + protected Content getNavLinkClass() { + Content linkContent = new RawHtml(getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, "", + configuration.getText("doclet.Class"), false))); + Content li = HtmlTree.LI(linkContent); + return li; } /** - * Print class use link + * Get the use link. + * + * @return a content tree for the use link */ - protected void navLinkClassUse() { - navCellRevStart(); - fontStyle("NavBarFont1Rev"); - strongText("doclet.navClassUse"); - fontEnd(); - navCellEnd(); + protected Content getNavLinkClassUse() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, useLabel); + return li; } - protected void navLinkTree() { - navCellStart(); - if (classdoc.containingPackage().isIncluded()) { - printHyperLink("../package-tree.html", "", - configuration.getText("doclet.Tree"), true, "NavBarFont1"); - } else { - printHyperLink(relativePath + "overview-tree.html", "", - configuration.getText("doclet.Tree"), true, "NavBarFont1"); - } - navCellEnd(); + /** + * Get the tree link. + * + * @return a content tree for the tree link + */ + protected Content getNavLinkTree() { + Content linkContent = classdoc.containingPackage().isIncluded() ? + getHyperLink("../package-tree.html", "", treeLabel) : + getHyperLink(relativePath + "overview-tree.html", "", treeLabel); + Content li = HtmlTree.LI(linkContent); + return li; } - } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java index acd8ff5c79c..bb805273502 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java @@ -32,6 +32,7 @@ import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.builders.*; import com.sun.tools.doclets.internal.toolkit.taglets.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Generate the Class Information Page. @@ -43,6 +44,7 @@ import com.sun.tools.doclets.internal.toolkit.taglets.*; * * @author Atul M Dambalkar * @author Robert Field + * @author Bhavesh Patel (Modified) */ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWriter { @@ -76,124 +78,173 @@ public class ClassWriterImpl extends SubWriterHolderWriter } /** - * Print this package link + * Get this package link. + * + * @return a content tree for the package link */ - protected void navLinkPackage() { - navCellStart(); - printHyperLink("package-summary.html", "", - configuration.getText("doclet.Package"), true, "NavBarFont1"); - navCellEnd(); + protected Content getNavLinkPackage() { + Content linkContent = getHyperLink("package-summary.html", "", + packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; } /** - * Print class page indicator + * Get the class link. + * + * @return a content tree for the class link */ - protected void navLinkClass() { - navCellRevStart(); - fontStyle("NavBarFont1Rev"); - strongText("doclet.Class"); - fontEnd(); - navCellEnd(); + protected Content getNavLinkClass() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, classLabel); + return li; } /** - * Print class use link + * Get the class use link. + * + * @return a content tree for the class use link */ - protected void navLinkClassUse() { - navCellStart(); - printHyperLink("class-use/" + filename, "", - configuration.getText("doclet.navClassUse"), true, "NavBarFont1"); - navCellEnd(); + protected Content getNavLinkClassUse() { + Content linkContent = getHyperLink("class-use/" + filename, "", useLabel); + Content li = HtmlTree.LI(linkContent); + return li; } /** - * Print previous package link + * Get link to previous class. + * + * @return a content tree for the previous class link */ - protected void navLinkPrevious() { - if (prev == null) { - printText("doclet.Prev_Class"); - } else { - printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS, prev, "", - configuration.getText("doclet.Prev_Class"), true)); + public Content getNavLinkPrevious() { + Content li; + if (prev != null) { + Content prevLink = new RawHtml(getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_CLASS, prev, "", + configuration.getText("doclet.Prev_Class"), true))); + li = HtmlTree.LI(prevLink); } + else + li = HtmlTree.LI(prevclassLabel); + return li; } /** - * Print next package link + * Get link to next class. + * + * @return a content tree for the next class link */ - protected void navLinkNext() { - if (next == null) { - printText("doclet.Next_Class"); - } else { - printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS, next, "", - configuration.getText("doclet.Next_Class"), true)); + public Content getNavLinkNext() { + Content li; + if (next != null) { + Content nextLink = new RawHtml(getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_CLASS, next, "", + configuration.getText("doclet.Next_Class"), true))); + li = HtmlTree.LI(nextLink); } + else + li = HtmlTree.LI(nextclassLabel); + return li; } /** * {@inheritDoc} */ - public void writeHeader(String header) { + public Content getHeader(String header) { String pkgname = (classDoc.containingPackage() != null)? classDoc.containingPackage().name(): ""; String clname = classDoc.name(); - printHtmlHeader(clname, - configuration.metakeywords.getMetaKeywords(classDoc), true); - printTop(); - navLinks(true); - hr(); - println(""); - h2(); + Content bodyTree = getBody(true, getWindowTitle(clname)); + addTop(bodyTree); + addNavLinks(true, bodyTree); + bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.header); if (pkgname.length() > 0) { - font("-1"); print(pkgname); fontEnd(); br(); + Content pkgNameContent = new StringContent(pkgname); + Content pkgNamePara = HtmlTree.P(HtmlStyle.subTitle, pkgNameContent); + div.addContent(pkgNamePara); } LinkInfoImpl linkInfo = new LinkInfoImpl( LinkInfoImpl.CONTEXT_CLASS_HEADER, - classDoc, false); + classDoc, false); //Let's not link to ourselves in the header. linkInfo.linkToSelf = false; - print(header + getTypeParameterLinks(linkInfo)); - h2End(); + Content headerContent = new StringContent(header); + Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, true, + HtmlStyle.title, headerContent); + heading.addContent(new RawHtml(getTypeParameterLinks(linkInfo))); + div.addContent(heading); + bodyTree.addContent(div); + return bodyTree; } /** * {@inheritDoc} */ - public void writeFooter() { - println(""); - hr(); - navLinks(false); - printBottom(); - printBodyHtmlEnd(); + public Content getClassContentHeader() { + return getContentHeader(); } /** * {@inheritDoc} */ - public void writeClassSignature(String modifiers) { + public void addFooter(Content contentTree) { + contentTree.addContent(HtmlConstants.END_OF_CLASS_DATA); + addNavLinks(false, contentTree); + addBottom(contentTree); + } + + /** + * {@inheritDoc} + */ + public void printDocument(Content contentTree) { + printHtmlDocument(configuration.metakeywords.getMetaKeywords(classDoc), + true, contentTree); + } + + /** + * {@inheritDoc} + */ + public Content getClassInfoTreeHeader() { + return getMemberTreeHeader(); + } + + /** + * {@inheritDoc} + */ + public Content getClassInfo(Content classInfoTree) { + return getMemberTree(HtmlStyle.description, classInfoTree); + } + + /** + * {@inheritDoc} + */ + public void addClassSignature(String modifiers, Content classInfoTree) { boolean isInterface = classDoc.isInterface(); - preNoNewLine(); - writeAnnotationInfo(classDoc); - print(modifiers); + classInfoTree.addContent(new HtmlTree(HtmlTag.BR)); + Content pre = new HtmlTree(HtmlTag.PRE); + addAnnotationInfo(classDoc, pre); + pre.addContent(modifiers); LinkInfoImpl linkInfo = new LinkInfoImpl( - LinkInfoImpl.CONTEXT_CLASS_SIGNATURE, classDoc, false); + LinkInfoImpl.CONTEXT_CLASS_SIGNATURE, classDoc, false); //Let's not link to ourselves in the signature. linkInfo.linkToSelf = false; - String name = classDoc.name() + - getTypeParameterLinks(linkInfo); + Content name = new RawHtml (classDoc.name() + + getTypeParameterLinks(linkInfo)); if (configuration().linksource) { - printSrcLink(classDoc, name); + addSrcLink(classDoc, name, pre); } else { - strong(name); + pre.addContent(HtmlTree.STRONG(name)); } if (!isInterface) { Type superclass = Util.getFirstVisibleSuperClass(classDoc, - configuration()); + configuration()); if (superclass != null) { - println(); - print("extends "); - printLink(new LinkInfoImpl( - LinkInfoImpl.CONTEXT_CLASS_SIGNATURE_PARENT_NAME, - superclass)); + pre.addContent("\n"); + pre.addContent("extends "); + Content link = new RawHtml(getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_CLASS_SIGNATURE_PARENT_NAME, + superclass))); + pre.addContent(link); } } Type[] implIntfacs = classDoc.interfaceTypes(); @@ -202,34 +253,33 @@ public class ClassWriterImpl extends SubWriterHolderWriter for (int i = 0; i < implIntfacs.length; i++) { ClassDoc classDoc = implIntfacs[i].asClassDoc(); if (! (classDoc.isPublic() || - Util.isLinkable(classDoc, configuration()))) { + Util.isLinkable(classDoc, configuration()))) { continue; } if (counter == 0) { - println(); - print(isInterface? "extends " : "implements "); + pre.addContent("\n"); + pre.addContent(isInterface? "extends " : "implements "); } else { - print(", "); + pre.addContent(", "); } - printLink(new LinkInfoImpl( - LinkInfoImpl.CONTEXT_CLASS_SIGNATURE_PARENT_NAME, - implIntfacs[i])); + Content link = new RawHtml(getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_CLASS_SIGNATURE_PARENT_NAME, + implIntfacs[i]))); + pre.addContent(link); counter++; } } - preEnd(); - p(); + classInfoTree.addContent(pre); } /** * {@inheritDoc} */ - public void writeClassDescription() { + public void addClassDescription(Content classInfoTree) { if(!configuration.nocomment) { // generate documentation for the class. if (classDoc.inlineTags().length > 0) { - printInlineComment(classDoc); - p(); + addInlineComment(classDoc, classInfoTree); } } } @@ -237,131 +287,118 @@ public class ClassWriterImpl extends SubWriterHolderWriter /** * {@inheritDoc} */ - public void writeClassTagInfo() { + public void addClassTagInfo(Content classInfoTree) { if(!configuration.nocomment) { // Print Information about all the tags here - printTags(classDoc); - hr(); - p(); - } else { - hr(); + addTagsInfo(classDoc, classInfoTree); } } /** - * {@inheritDoc} - */ - public void writeClassDeprecationInfo() { - hr(); - Tag[] deprs = classDoc.tags("deprecated"); - if (Util.isDeprecated(classDoc)) { - strongText("doclet.Deprecated"); - if (deprs.length > 0) { - Tag[] commentTags = deprs[0].inlineTags(); - if (commentTags.length > 0) { - space(); - printInlineDeprecatedComment(classDoc, deprs[0]); - } - } - p(); - } - } - - /** - * Generate the indent and get the line image for the class tree. - * For user accessibility, the image includes the alt attribute - * "extended by". (This method is not intended for a class - * implementing an interface, where "implemented by" would be required.) + * Get the class hierarchy tree for the given class. * - * indent integer indicating the number of spaces to indent + * @param type the class to print the hierarchy for + * @return a content tree for class inheritence */ - private void writeStep(int indent) { - print(spaces(4 * indent - 2)); - print(""); + private Content getClassInheritenceTree(Type type) { + Type sup; + HtmlTree classTreeUl = new HtmlTree(HtmlTag.UL); + classTreeUl.addStyle(HtmlStyle.inheritance); + Content liTree = null; + do { + sup = Util.getFirstVisibleSuperClass( + type instanceof ClassDoc ? (ClassDoc) type : type.asClassDoc(), + configuration()); + if (sup != null) { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.inheritance); + ul.addContent(getTreeForClassHelper(type)); + if (liTree != null) + ul.addContent(liTree); + Content li = HtmlTree.LI(ul); + liTree = li; + type = sup; + } + else + classTreeUl.addContent(getTreeForClassHelper(type)); + } + while (sup != null); + if (liTree != null) + classTreeUl.addContent(liTree); + return classTreeUl; } /** - * Print the class hierarchy tree for the given class. - * @param type the class to print the hierarchy for. - * @return return the amount that should be indented in - * the next level of the tree. + * Get the class helper tree for the given class. + * + * @param type the class to print the helper for + * @return a content tree for class helper */ - private int writeTreeForClassHelper(Type type) { - Type sup = Util.getFirstVisibleSuperClass( - type instanceof ClassDoc ? (ClassDoc) type : type.asClassDoc(), - configuration()); - int indent = 0; - if (sup != null) { - indent = writeTreeForClassHelper(sup); - writeStep(indent); - } - + private Content getTreeForClassHelper(Type type) { + Content li = new HtmlTree(HtmlTag.LI); if (type.equals(classDoc)) { String typeParameters = getTypeParameterLinks( - new LinkInfoImpl( - LinkInfoImpl.CONTEXT_TREE, + new LinkInfoImpl(LinkInfoImpl.CONTEXT_TREE, classDoc, false)); if (configuration.shouldExcludeQualifier( classDoc.containingPackage().name())) { - strong(type.asClassDoc().name() + typeParameters); + li.addContent(type.asClassDoc().name()); + li.addContent(new RawHtml(typeParameters)); } else { - strong(type.asClassDoc().qualifiedName() + typeParameters); + li.addContent(type.asClassDoc().qualifiedName()); + li.addContent(new RawHtml(typeParameters)); } } else { - print(getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_TREE_PARENT, + Content link = new RawHtml(getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_CLASS_TREE_PARENT, type instanceof ClassDoc ? (ClassDoc) type : type, configuration.getClassName(type.asClassDoc()), false))); + li.addContent(link); } - println(); - return indent + 1; + return li; } /** - * Print the class hierarchy tree for this class only. + * {@inheritDoc} */ - public void writeClassTree() { - if (! classDoc.isClass()) { + public void addClassTree(Content classContentTree) { + if (!classDoc.isClass()) { return; } - pre(); - writeTreeForClassHelper(classDoc); - preEnd(); + classContentTree.addContent(getClassInheritenceTree(classDoc)); } /** - * Write the type parameter information. + * {@inheritDoc} */ - public void writeTypeParamInfo() { + public void addTypeParamInfo(Content classInfoTree) { if (classDoc.typeParamTags().length > 0) { - dl(); - dt(); TagletOutput output = (new ParamTaglet()).getTagletOutput(classDoc, - getTagletWriterInstance(false)); - print(output.toString()); - dtEnd(); - dlEnd(); + getTagletWriterInstance(false)); + Content typeParam = new RawHtml(output.toString()); + Content dl = HtmlTree.DL(typeParam); + classInfoTree.addContent(dl); } } /** * {@inheritDoc} */ - public void writeSubClassInfo() { + public void addSubClassInfo(Content classInfoTree) { if (classDoc.isClass()) { if (classDoc.qualifiedName().equals("java.lang.Object") || - classDoc.qualifiedName().equals("org.omg.CORBA.Object")) { + classDoc.qualifiedName().equals("org.omg.CORBA.Object")) { return; // Don't generate the list, too huge } List subclasses = classtree.subs(classDoc, false); if (subclasses.size() > 0) { - dl(); - dt(); - strongText("doclet.Subclasses"); - dtEnd(); - writeClassLinks(LinkInfoImpl.CONTEXT_SUBCLASSES, - subclasses); - dlEnd(); + Content label = getResource( + "doclet.Subclasses"); + Content dt = HtmlTree.DT(label); + Content dl = HtmlTree.DL(dt); + dl.addContent(getClassLinks(LinkInfoImpl.CONTEXT_SUBCLASSES, + subclasses)); + classInfoTree.addContent(dl); } } } @@ -369,140 +406,196 @@ public class ClassWriterImpl extends SubWriterHolderWriter /** * {@inheritDoc} */ - public void writeSubInterfacesInfo() { + public void addSubInterfacesInfo(Content classInfoTree) { if (classDoc.isInterface()) { List subInterfaces = classtree.allSubs(classDoc, false); if (subInterfaces.size() > 0) { - dl(); - dt(); - strongText("doclet.Subinterfaces"); - dtEnd(); - writeClassLinks(LinkInfoImpl.CONTEXT_SUBINTERFACES, - subInterfaces); - dlEnd(); + Content label = getResource( + "doclet.Subinterfaces"); + Content dt = HtmlTree.DT(label); + Content dl = HtmlTree.DL(dt); + dl.addContent(getClassLinks(LinkInfoImpl.CONTEXT_SUBINTERFACES, + subInterfaces)); + classInfoTree.addContent(dl); } } } /** - * If this is the interface which are the classes, that implement this? + * {@inheritDoc} */ - public void writeInterfaceUsageInfo () { + public void addInterfaceUsageInfo (Content classInfoTree) { if (! classDoc.isInterface()) { return; } if (classDoc.qualifiedName().equals("java.lang.Cloneable") || - classDoc.qualifiedName().equals("java.io.Serializable")) { + classDoc.qualifiedName().equals("java.io.Serializable")) { return; // Don't generate the list, too big } List implcl = classtree.implementingclasses(classDoc); if (implcl.size() > 0) { - dl(); - dt(); - strongText("doclet.Implementing_Classes"); - dtEnd(); - writeClassLinks(LinkInfoImpl.CONTEXT_IMPLEMENTED_CLASSES, - implcl); - dlEnd(); + Content label = getResource( + "doclet.Implementing_Classes"); + Content dt = HtmlTree.DT(label); + Content dl = HtmlTree.DL(dt); + dl.addContent(getClassLinks(LinkInfoImpl.CONTEXT_IMPLEMENTED_CLASSES, + implcl)); + classInfoTree.addContent(dl); } } /** * {@inheritDoc} */ - public void writeImplementedInterfacesInfo() { + public void addImplementedInterfacesInfo(Content classInfoTree) { //NOTE: we really should be using ClassDoc.interfaceTypes() here, but // it doesn't walk up the tree like we want it to. List interfaceArray = Util.getAllInterfaces(classDoc, configuration); if (classDoc.isClass() && interfaceArray.size() > 0) { - dl(); - dt(); - strongText("doclet.All_Implemented_Interfaces"); - dtEnd(); - writeClassLinks(LinkInfoImpl.CONTEXT_IMPLEMENTED_INTERFACES, - interfaceArray); - dlEnd(); + Content label = getResource( + "doclet.All_Implemented_Interfaces"); + Content dt = HtmlTree.DT(label); + Content dl = HtmlTree.DL(dt); + dl.addContent(getClassLinks(LinkInfoImpl.CONTEXT_IMPLEMENTED_INTERFACES, + interfaceArray)); + classInfoTree.addContent(dl); } } /** * {@inheritDoc} */ - public void writeSuperInterfacesInfo() { + public void addSuperInterfacesInfo(Content classInfoTree) { //NOTE: we really should be using ClassDoc.interfaceTypes() here, but // it doesn't walk up the tree like we want it to. List interfaceArray = Util.getAllInterfaces(classDoc, configuration); if (classDoc.isInterface() && interfaceArray.size() > 0) { - dl(); - dt(); - strongText("doclet.All_Superinterfaces"); - dtEnd(); - writeClassLinks(LinkInfoImpl.CONTEXT_SUPER_INTERFACES, - interfaceArray); - dlEnd(); + Content label = getResource( + "doclet.All_Superinterfaces"); + Content dt = HtmlTree.DT(label); + Content dl = HtmlTree.DL(dt); + dl.addContent(getClassLinks(LinkInfoImpl.CONTEXT_SUPER_INTERFACES, + interfaceArray)); + classInfoTree.addContent(dl); } } /** - * Generate links to the given classes. + * {@inheritDoc} */ - private void writeClassLinks(int context, List list) { + public void addNestedClassInfo(Content classInfoTree) { + ClassDoc outerClass = classDoc.containingClass(); + if (outerClass != null) { + Content label; + if (outerClass.isInterface()) { + label = getResource( + "doclet.Enclosing_Interface"); + } else { + label = getResource( + "doclet.Enclosing_Class"); + } + Content dt = HtmlTree.DT(label); + Content dl = HtmlTree.DL(dt); + Content dd = new HtmlTree(HtmlTag.DD); + dd.addContent(new RawHtml(getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS, outerClass, + false)))); + dl.addContent(dd); + classInfoTree.addContent(dl); + } + } + + /** + * {@inheritDoc} + */ + public void addClassDeprecationInfo(Content classInfoTree) { + Content hr = new HtmlTree(HtmlTag.HR); + classInfoTree.addContent(hr); + Tag[] deprs = classDoc.tags("deprecated"); + if (Util.isDeprecated(classDoc)) { + Content strong = HtmlTree.STRONG(deprecatedPhrase); + Content div = HtmlTree.DIV(HtmlStyle.block, strong); + if (deprs.length > 0) { + Tag[] commentTags = deprs[0].inlineTags(); + if (commentTags.length > 0) { + div.addContent(getSpace()); + addInlineDeprecatedComment(classDoc, deprs[0], div); + } + } + classInfoTree.addContent(div); + } + } + + /** + * Get links to the given classes. + * + * @param context the id of the context where the link will be printed + * @param list the list of classes + * @return a content tree for the class list + */ + private Content getClassLinks(int context, List list) { Object[] typeList = list.toArray(); - //Sort the list to be printed. - print(' '); - dd(); + Content dd = new HtmlTree(HtmlTag.DD); for (int i = 0; i < list.size(); i++) { if (i > 0) { - print(", "); + Content separator = new StringContent(", "); + dd.addContent(separator); } if (typeList[i] instanceof ClassDoc) { - printLink(new LinkInfoImpl(context, (ClassDoc)(typeList[i]))); - + Content link = new RawHtml(getLink( + new LinkInfoImpl(context, (ClassDoc)(typeList[i])))); + dd.addContent(link); } else { - printLink(new LinkInfoImpl(context, (Type)(typeList[i]))); + Content link = new RawHtml(getLink( + new LinkInfoImpl(context, (Type)(typeList[i])))); + dd.addContent(link); } } - ddEnd(); + return dd; } - protected void navLinkTree() { - navCellStart(); - printHyperLink("package-tree.html", "", - configuration.getText("doclet.Tree"), true, "NavBarFont1"); - navCellEnd(); + /** + * {@inheritDoc} + */ + protected Content getNavLinkTree() { + Content treeLinkContent = getHyperLink("package-tree.html", + "", treeLabel, "", ""); + Content li = HtmlTree.LI(treeLinkContent); + return li; } - protected void printSummaryDetailLinks() { + /** + * Add summary details to the navigation bar. + * + * @param subDiv the content tree to which the summary detail links will be added + */ + protected void addSummaryDetailLinks(Content subDiv) { try { - tr(); - tdVAlignClass("top", "NavBarCell3"); - font("-2"); - print(" "); - navSummaryLinks(); - fontEnd(); - tdEnd(); - tdVAlignClass("top", "NavBarCell3"); - font("-2"); - navDetailLinks(); - fontEnd(); - tdEnd(); - trEnd(); + Content div = HtmlTree.DIV(getNavSummaryLinks()); + div.addContent(getNavDetailLinks()); + subDiv.addContent(div); } catch (Exception e) { e.printStackTrace(); throw new DocletAbortException(); } } - protected void navSummaryLinks() throws Exception { - printText("doclet.Summary"); - space(); + /** + * Get summary links for navigation bar. + * + * @return the content tree for the navigation summary links + */ + protected Content getNavSummaryLinks() throws Exception { + Content li = HtmlTree.LI(summaryLabel); + li.addContent(getSpace()); + Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) - configuration.getBuilderFactory().getMemberSummaryBuilder(this); + configuration.getBuilderFactory().getMemberSummaryBuilder(this); String[] navLinkLabels = new String[] { "doclet.navNested", "doclet.navEnum", "doclet.navField", "doclet.navConstructor", - "doclet.navMethod" + "doclet.navMethod" }; for (int i = 0; i < navLinkLabels.length; i++ ) { + Content liNav = new HtmlTree(HtmlTag.LI); if (i == VisibleMemberMap.ENUM_CONSTANTS && ! classDoc.isEnum()) { continue; } @@ -511,38 +604,41 @@ public class ClassWriterImpl extends SubWriterHolderWriter } AbstractMemberWriter writer = ((AbstractMemberWriter) memberSummaryBuilder. - getMemberSummaryWriter(i)); + getMemberSummaryWriter(i)); if (writer == null) { - printText(navLinkLabels[i]); + liNav.addContent(getResource(navLinkLabels[i])); } else { - writer.navSummaryLink( - memberSummaryBuilder.members(i), - memberSummaryBuilder.getVisibleMemberMap(i)); + writer.addNavSummaryLink( + memberSummaryBuilder.members(i), + memberSummaryBuilder.getVisibleMemberMap(i), liNav); } if (i < navLinkLabels.length-1) { - navGap(); + addNavGap(liNav); } + ulNav.addContent(liNav); } + return ulNav; } /** - * Method navDetailLinks - * - * @throws Exception + * Get detail links for the navigation bar. * + * @return the content tree for the detail links */ - protected void navDetailLinks() throws Exception { - printText("doclet.Detail"); - space(); + protected Content getNavDetailLinks() throws Exception { + Content li = HtmlTree.LI(detailLabel); + li.addContent(getSpace()); + Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) - configuration.getBuilderFactory().getMemberSummaryBuilder(this); + configuration.getBuilderFactory().getMemberSummaryBuilder(this); String[] navLinkLabels = new String[] { "doclet.navNested", "doclet.navEnum", "doclet.navField", "doclet.navConstructor", - "doclet.navMethod" + "doclet.navMethod" }; for (int i = 1; i < navLinkLabels.length; i++ ) { + Content liNav = new HtmlTree(HtmlTag.LI); AbstractMemberWriter writer = - ((AbstractMemberWriter) memberSummaryBuilder. + ((AbstractMemberWriter) memberSummaryBuilder. getMemberSummaryWriter(i)); if (i == VisibleMemberMap.ENUM_CONSTANTS && ! classDoc.isEnum()) { continue; @@ -551,43 +647,27 @@ public class ClassWriterImpl extends SubWriterHolderWriter continue; } if (writer == null) { - printText(navLinkLabels[i]); + liNav.addContent(getResource(navLinkLabels[i])); } else { - writer.navDetailLink(memberSummaryBuilder.members(i)); + writer.addNavDetailLink(memberSummaryBuilder.members(i), liNav); } if (i < navLinkLabels.length - 1) { - navGap(); + addNavGap(liNav); } + ulNav.addContent(liNav); } - } - - protected void navGap() { - space(); - print('|'); - space(); + return ulNav; } /** - * If this is an inner class or interface, write the enclosing class or - * interface. + * Add gap between navigation bar elements. + * + * @param liNav the content tree to which the gap will be added */ - public void writeNestedClassInfo() { - ClassDoc outerClass = classDoc.containingClass(); - if (outerClass != null) { - dl(); - dt(); - if (outerClass.isInterface()) { - strongText("doclet.Enclosing_Interface"); - } else { - strongText("doclet.Enclosing_Class"); - } - dtEnd(); - dd(); - printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS, outerClass, - false)); - ddEnd(); - dlEnd(); - } + protected void addNavGap(Content liNav) { + liNav.addContent(getSpace()); + liNav.addContent("|"); + liNav.addContent(getSpace()); } /** @@ -598,11 +678,4 @@ public class ClassWriterImpl extends SubWriterHolderWriter public ClassDoc getClassDoc() { return classDoc; } - - /** - * {@inheritDoc} - */ - public void completeMemberSummaryBuild() { - p(); - } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java index 0b0bfa29382..381ca0957f7 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java @@ -25,11 +25,12 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.*; -import com.sun.tools.doclets.internal.toolkit.util.*; -import com.sun.javadoc.*; import java.io.*; import java.util.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Write the Constants Summary Page in HTML format. @@ -76,67 +77,106 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter /** * {@inheritDoc} */ - public void writeHeader() { - printHtmlHeader(configuration.getText("doclet.Constants_Summary"), - null, true); - printTop(); - navLinks(true); - hr(); - - center(); - h1(); printText("doclet.Constants_Summary"); h1End(); - centerEnd(); - - hr(4, "noshade"); + public Content getHeader() { + String label = configuration.getText("doclet.Constants_Summary"); + Content bodyTree = getBody(true, getWindowTitle(label)); + addTop(bodyTree); + addNavLinks(true, bodyTree); + return bodyTree; } /** * {@inheritDoc} */ - public void writeFooter() { - hr(); - navLinks(false); - printBottom(); - printBodyHtmlEnd(); + public Content getContentsHeader() { + return new HtmlTree(HtmlTag.UL); } /** * {@inheritDoc} */ - public void writeContentsHeader() { - strong(configuration.getText("doclet.Contents")); - ul(); - } - - /** - * {@inheritDoc} - */ - public void writeContentsFooter() { - ulEnd(); - println(); - } - - /** - * {@inheritDoc} - */ - public void writeLinkToPackageContent(PackageDoc pkg, String parsedPackageName, Set printedPackageHeaders) { + public void addLinkToPackageContent(PackageDoc pkg, String parsedPackageName, + Set printedPackageHeaders, Content contentListTree) { String packageName = pkg.name(); //add link to summary - li(); + Content link; if (packageName.length() == 0) { - printHyperLink("#" + DocletConstants.UNNAMED_PACKAGE_ANCHOR, - DocletConstants.DEFAULT_PACKAGE_NAME); + link = getHyperLink("#" + DocletConstants.UNNAMED_PACKAGE_ANCHOR, + "", defaultPackageLabel, "", ""); } else { - printHyperLink("#" + parsedPackageName, parsedPackageName + ".*"); + Content packageNameContent = getPackageLabel(parsedPackageName); + packageNameContent.addContent(".*"); + link = getHyperLink("#" + parsedPackageName, + "", packageNameContent, "", ""); printedPackageHeaders.add(parsedPackageName); } - println(); + contentListTree.addContent(HtmlTree.LI(link)); } /** * {@inheritDoc} */ - public void writeConstantMembersHeader(ClassDoc cd) { + public Content getContentsList(Content contentListTree) { + Content titleContent = getResource( + "doclet.Constants_Summary"); + Content pHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.title, titleContent); + Content div = HtmlTree.DIV(HtmlStyle.header, pHeading); + Content headingContent = getResource( + "doclet.Contents"); + div.addContent(HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, true, + headingContent)); + div.addContent(contentListTree); + return div; + } + + /** + * {@inheritDoc} + */ + public Content getConstantSummaries() { + HtmlTree summariesDiv = new HtmlTree(HtmlTag.DIV); + summariesDiv.addStyle(HtmlStyle.constantValuesContainer); + return summariesDiv; + } + + /** + * {@inheritDoc} + */ + public void addPackageName(PackageDoc pkg, String parsedPackageName, + Content summariesTree) { + Content pkgNameContent; + if (parsedPackageName.length() == 0) { + summariesTree.addContent(getMarkerAnchor( + DocletConstants.UNNAMED_PACKAGE_ANCHOR)); + pkgNameContent = defaultPackageLabel; + } else { + summariesTree.addContent(getMarkerAnchor( + parsedPackageName)); + pkgNameContent = getPackageLabel(parsedPackageName); + } + Content headingContent = new StringContent(".*"); + Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, + pkgNameContent); + heading.addContent(headingContent); + summariesTree.addContent(heading); + } + + /** + * {@inheritDoc} + */ + public Content getClassConstantHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * Get the table caption and header for the constant summary table + * + * @param cd classdoc to be documented + * @return constant members header content + */ + public Content getConstantMembersHeader(ClassDoc cd) { //generate links backward only to public classes. String classlink = (cd.isPublic() || cd.isProtected())? getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CONSTANT_SUMMARY, cd, @@ -144,112 +184,120 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter cd.qualifiedName(); String name = cd.containingPackage().name(); if (name.length() > 0) { - writeClassName(name + "." + classlink); + return getClassName(name + "." + classlink); } else { - writeClassName(classlink); + return getClassName(classlink); } } + /** + * Get the class name in the table caption and the table header. + * + * @param classStr the class name to print. + * @return the table caption and header + */ + protected Content getClassName(String classStr) { + Content table = HtmlTree.TABLE(0, 3, 0, constantsTableSummary, + getTableCaption(classStr)); + table.addContent(getSummaryTableHeader(constantsTableHeader, "col")); + return table; + } + /** * {@inheritDoc} */ - public void writeConstantMembersFooter(ClassDoc cd) { - tableFooter(false); - p(); - } - - /** - * Print the class name in the table heading. - * @param classStr the heading to print. - */ - protected void writeClassName(String classStr) { - table(1, 3, 0, constantsTableSummary); - tableSubCaptionStart(); - write(classStr); - tableCaptionEnd(); - summaryTableHeader(constantsTableHeader, "col"); - } - - private void tableFooter(boolean isHeader) { - fontEnd(); - if (isHeader) { - thEnd(); - } else { - tdEnd(); - } - trEnd(); - tableEnd(); - p(); - } - - /** - * {@inheritDoc} - */ - public void writePackageName(PackageDoc pkg, String parsedPackageName) { - String pkgname; - if (parsedPackageName.length() == 0) { - anchor(DocletConstants.UNNAMED_PACKAGE_ANCHOR); - pkgname = DocletConstants.DEFAULT_PACKAGE_NAME; - } else { - anchor(parsedPackageName); - pkgname = parsedPackageName; - } - table(1, "100%", 3, 0); - trBgcolorStyle("#CCCCFF", "TableHeadingColor"); - thAlign("left"); - font("+2"); - write(pkgname + ".*"); - tableFooter(true); - } - - /** - * {@inheritDoc} - */ - public void writeConstantMembers(ClassDoc cd, List fields) { + public void addConstantMembers(ClassDoc cd, List fields, + Content classConstantTree) { currentClassDoc = cd; + Content tbody = new HtmlTree(HtmlTag.TBODY); for (int i = 0; i < fields.size(); ++i) { - writeConstantMember(fields.get(i)); + HtmlTree tr = new HtmlTree(HtmlTag.TR); + if (i%2 == 0) + tr.addStyle(HtmlStyle.altColor); + else + tr.addStyle(HtmlStyle.rowColor); + addConstantMember(fields.get(i), tr); + tbody.addContent(tr); } + Content table = getConstantMembersHeader(cd); + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + classConstantTree.addContent(li); } - private void writeConstantMember(FieldDoc member) { - trBgcolorStyle("white", "TableRowColor"); - anchor(currentClassDoc.qualifiedName() + "." + member.name()); - writeTypeColumn(member); - writeNameColumn(member); - writeValue(member); - trEnd(); + /** + * Add the row for the constant summary table. + * + * @param member the field to be documented. + * @param trTree an htmltree object for the table row + */ + private void addConstantMember(FieldDoc member, HtmlTree trTree) { + trTree.addContent(getTypeColumn(member)); + trTree.addContent(getNameColumn(member)); + trTree.addContent(getValue(member)); } - private void writeTypeColumn(FieldDoc member) { - tdAlign("right"); - font("-1"); - code(); + /** + * Get the type column for the constant summary table row. + * + * @param member the field to be documented. + * @return the type column of the constant table row + */ + private Content getTypeColumn(FieldDoc member) { + Content anchor = getMarkerAnchor(currentClassDoc.qualifiedName() + + "." + member.name()); + Content tdType = HtmlTree.TD(HtmlStyle.colFirst, anchor); + Content code = new HtmlTree(HtmlTag.CODE); StringTokenizer mods = new StringTokenizer(member.modifiers()); while(mods.hasMoreTokens()) { - print(mods.nextToken() + " "); + Content modifier = new StringContent(mods.nextToken()); + code.addContent(modifier); + code.addContent(getSpace()); } - printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CONSTANT_SUMMARY, - member.type())); - codeEnd(); - fontEnd(); - tdEnd(); + Content type = new RawHtml(getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_CONSTANT_SUMMARY, member.type()))); + code.addContent(type); + tdType.addContent(code); + return tdType; } - private void writeNameColumn(FieldDoc member) { - tdAlign("left"); - code(); - printDocLink(LinkInfoImpl.CONTEXT_CONSTANT_SUMMARY, member, - member.name(), false); - codeEnd(); - tdEnd(); + /** + * Get the name column for the constant summary table row. + * + * @param member the field to be documented. + * @return the name column of the constant table row + */ + private Content getNameColumn(FieldDoc member) { + Content nameContent = new RawHtml(getDocLink( + LinkInfoImpl.CONTEXT_CONSTANT_SUMMARY, member, member.name(), false)); + Content code = HtmlTree.CODE(nameContent); + return HtmlTree.TD(code); } - private void writeValue(FieldDoc member) { - tdAlign("right"); - code(); - print(Util.escapeHtmlChars(member.constantValueExpression())); - codeEnd(); - tdEnd(); + /** + * Get the value column for the constant summary table row. + * + * @param member the field to be documented. + * @return the value column of the constant table row + */ + private Content getValue(FieldDoc member) { + Content valueContent = new StringContent(member.constantValueExpression()); + Content code = HtmlTree.CODE(valueContent); + return HtmlTree.TD(HtmlStyle.colLast, code); + } + + /** + * {@inheritDoc} + */ + public void addFooter(Content contentTree) { + addNavLinks(false, contentTree); + addBottom(contentTree); + } + + /** + * {@inheritDoc} + */ + public void printDocument(Content contentTree) { + printHtmlDocument(null, true, contentTree); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java index 0d5f6b8895a..edd1b9d0ee2 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java @@ -29,6 +29,7 @@ import java.io.*; import java.util.*; import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; @@ -43,7 +44,6 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter implements ConstructorWriter, MemberSummaryWriter { private boolean foundNonPubConstructor = false; - private boolean printedSummaryHeader = false; /** * Construct a new ConstructorWriterImpl. @@ -75,125 +75,112 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter } /** - * Write the constructors summary header for the given class. - * - * @param classDoc the class the summary belongs to. + * {@inheritDoc} */ - public void writeMemberSummaryHeader(ClassDoc classDoc) { - printedSummaryHeader = true; - writer.println(); - writer.println(""); - writer.println(); - writer.printSummaryHeader(this, classDoc); + public Content getMemberSummaryHeader(ClassDoc classDoc, + Content memberSummaryTree) { + memberSummaryTree.addContent(HtmlConstants.START_OF_CONSTRUCTOR_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, classDoc, memberTree); + return memberTree; } /** - * Write the constructors summary footer for the given class. - * - * @param classDoc the class the summary belongs to. + * {@inheritDoc} */ - public void writeMemberSummaryFooter(ClassDoc classDoc) { - writer.printSummaryFooter(this, classDoc); + public Content getConstructorDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree) { + memberDetailsTree.addContent(HtmlConstants.START_OF_CONSTRUCTOR_DETAILS); + Content constructorDetailsTree = writer.getMemberTreeHeader(); + constructorDetailsTree.addContent(writer.getMarkerAnchor("constructor_detail")); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.constructorDetailsLabel); + constructorDetailsTree.addContent(heading); + return constructorDetailsTree; } /** - * Write the header for the constructor documentation. - * - * @param classDoc the class that the constructors belong to. + * {@inheritDoc} */ - public void writeHeader(ClassDoc classDoc, String header) { - writer.println(); - writer.println(""); - writer.println(); - writer.anchor("constructor_detail"); - writer.printTableHeadingBackground(header); - } - - /** - * Write the constructor header for the given constructor. - * - * @param constructor the constructor being documented. - * @param isFirst the flag to indicate whether or not the constructor is the - * first to be documented. - */ - public void writeConstructorHeader(ConstructorDoc constructor, boolean isFirst) { - if (! isFirst) { - writer.printMemberHeader(); - } - writer.println(); + public Content getConstructorDocTreeHeader(ConstructorDoc constructor, + Content constructorDetailsTree) { String erasureAnchor; if ((erasureAnchor = getErasureAnchor(constructor)) != null) { - writer.anchor(erasureAnchor); + constructorDetailsTree.addContent(writer.getMarkerAnchor((erasureAnchor))); } - writer.anchor(constructor); - writer.h3(); - writer.print(constructor.name()); - writer.h3End(); + constructorDetailsTree.addContent( + writer.getMarkerAnchor(writer.getAnchor(constructor))); + Content constructorDocTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(constructor.name()); + constructorDocTree.addContent(heading); + return constructorDocTree; } /** - * Write the signature for the given constructor. - * - * @param constructor the constructor being documented. + * {@inheritDoc} */ - public void writeSignature(ConstructorDoc constructor) { + public Content getSignature(ConstructorDoc constructor) { writer.displayLength = 0; - writer.pre(); - writer.writeAnnotationInfo(constructor); - printModifiers(constructor); - //printReturnType((ConstructorDoc)constructor); + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(constructor, pre); + addModifiers(constructor, pre); if (configuration().linksource) { - writer.printSrcLink(constructor, constructor.name()); + Content constructorName = new StringContent(constructor.name()); + writer.addSrcLink(constructor, constructorName, pre); } else { - strong(constructor.name()); + addName(constructor.name(), pre); } - writeParameters(constructor); - writeExceptions(constructor); - writer.preEnd(); - assert !writer.getMemberDetailsListPrinted(); + addParameters(constructor, pre); + addExceptions(constructor, pre); + return pre; } /** - * Write the deprecated output for the given constructor. - * - * @param constructor the constructor being documented. + * {@inheritDoc} */ - public void writeDeprecated(ConstructorDoc constructor) { - printDeprecated(constructor); + @Override + public void setSummaryColumnStyle(HtmlTree tdTree) { + if (foundNonPubConstructor) + tdTree.addStyle(HtmlStyle.colLast); + else + tdTree.addStyle(HtmlStyle.colOne); } /** - * Write the comments for the given constructor. - * - * @param constructor the constructor being documented. + * {@inheritDoc} */ - public void writeComments(ConstructorDoc constructor) { - printComment(constructor); + public void addDeprecated(ConstructorDoc constructor, Content constructorDocTree) { + addDeprecatedInfo(constructor, constructorDocTree); } /** - * Write the tag output for the given constructor. - * - * @param constructor the constructor being documented. + * {@inheritDoc} */ - public void writeTags(ConstructorDoc constructor) { - writer.printTags(constructor); + public void addComments(ConstructorDoc constructor, Content constructorDocTree) { + addComment(constructor, constructorDocTree); } /** - * Write the constructor footer. + * {@inheritDoc} */ - public void writeConstructorFooter() { - printMemberFooter(); + public void addTags(ConstructorDoc constructor, Content constructorDocTree) { + writer.addTagsInfo(constructor, constructorDocTree); } /** - * Write the footer for the constructor documentation. - * - * @param classDoc the class that the constructors belong to. + * {@inheritDoc} */ - public void writeFooter(ClassDoc classDoc) { - //No footer to write for constructor documentation + public Content getConstructorDetails(Content constructorDetailsTree) { + return getMemberTree(constructorDetailsTree); + } + + /** + * {@inheritDoc} + */ + public Content getConstructorDoc(Content constructorDocTree, + boolean isLastContent) { + return getMemberTree(constructorDocTree, isLastContent); } /** @@ -212,17 +199,35 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter this.foundNonPubConstructor = foundNonPubConstructor; } - public void printSummaryLabel() { - writer.printText("doclet.Constructor_Summary"); + /** + * {@inheritDoc} + */ + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Constructor_Summary")); + memberTree.addContent(label); } - public void printTableSummary() { - writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + /** + * {@inheritDoc} + */ + public String getTableSummary() { + return configuration().getText("doclet.Member_Table_Summary", configuration().getText("doclet.Constructor_Summary"), - configuration().getText("doclet.constructors"))); + configuration().getText("doclet.constructors")); } - public void printSummaryTableHeader(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + public String getCaption() { + return configuration().getText("doclet.Constructors"); + } + + /** + * {@inheritDoc} + */ + public String[] getSummaryTableHeader(ProgramElementDoc member) { String[] header; if (foundNonPubConstructor) { header = new String[] { @@ -239,87 +244,73 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter configuration().getText("doclet.Description")) }; } - writer.summaryTableHeader(header, "col"); + return header; } - public void printSummaryAnchor(ClassDoc cd) { - writer.anchor("constructor_summary"); + /** + * {@inheritDoc} + */ + public void addSummaryAnchor(ClassDoc cd, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor("constructor_summary")); } - public void printInheritedSummaryAnchor(ClassDoc cd) { - } // no such + /** + * {@inheritDoc} + */ + public void addInheritedSummaryAnchor(ClassDoc cd, Content inheritedTree) { + } - public void printInheritedSummaryLabel(ClassDoc cd) { - // no such + /** + * {@inheritDoc} + */ + public void addInheritedSummaryLabel(ClassDoc cd, Content inheritedTree) { } public int getMemberKind() { return VisibleMemberMap.CONSTRUCTORS; } - protected void navSummaryLink(List members) { - printNavSummaryLink(classdoc, - members.size() > 0? true: false); - } - - protected void printNavSummaryLink(ClassDoc cd, boolean link) { - if (link) { - writer.printHyperLink("", "constructor_summary", - ConfigurationImpl.getInstance().getText("doclet.navConstructor")); - } else { - writer.printText("doclet.navConstructor"); - } - } - - protected void printNavDetailLink(boolean link) { - if (link) { - writer.printHyperLink("", "constructor_detail", - ConfigurationImpl.getInstance().getText("doclet.navConstructor")); - } else { - writer.printText("doclet.navConstructor"); - } - } - - protected void printSummaryType(ProgramElementDoc member) { - if (foundNonPubConstructor) { - writer.printTypeSummaryHeader(); - if (member.isProtected()) { - print("protected "); - } else if (member.isPrivate()) { - print("private "); - } else if (member.isPublic()) { - writer.space(); - } else { - writer.printText("doclet.Package_private"); - } - writer.printTypeSummaryFooter(); - } - } - /** - * Write the inherited member summary header for the given class. - * - * @param classDoc the class the summary belongs to. + * {@inheritDoc} */ - public void writeInheritedMemberSummaryHeader(ClassDoc classDoc) { - if(! printedSummaryHeader){ - //We don't want inherited summary to not be under heading. - writeMemberSummaryHeader(classDoc); - writeMemberSummaryFooter(classDoc); - printedSummaryHeader = true; + protected Content getNavSummaryLink(ClassDoc cd, boolean link) { + if (link) { + return writer.getHyperLink("", "constructor_summary", + writer.getResource("doclet.navConstructor")); + } else { + return writer.getResource("doclet.navConstructor"); } } /** * {@inheritDoc} */ - public void writeInheritedMemberSummary(ClassDoc classDoc, - ProgramElementDoc member, boolean isFirst, boolean isLast) {} + protected void addNavDetailLink(boolean link, Content liNav) { + if (link) { + liNav.addContent(writer.getHyperLink("", "constructor_detail", + writer.getResource("doclet.navConstructor"))); + } else { + liNav.addContent(writer.getResource("doclet.navConstructor")); + } + } /** - * Write the inherited member summary footer for the given class. - * - * @param classDoc the class the summary belongs to. + * {@inheritDoc} */ - public void writeInheritedMemberSummaryFooter(ClassDoc classDoc) {} + protected void addSummaryType(ProgramElementDoc member, Content tdSummaryType) { + if (foundNonPubConstructor) { + Content code = new HtmlTree(HtmlTag.CODE); + if (member.isProtected()) { + code.addContent("protected "); + } else if (member.isPrivate()) { + code.addContent("private "); + } else if (member.isPublic()) { + code.addContent(writer.getSpace()); + } else { + code.addContent( + configuration().getText("doclet.Package_private")); + } + tdSummaryType.addContent(code); + } + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java index f0a6bfed3d6..15867891115 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java @@ -25,9 +25,11 @@ package com.sun.tools.doclets.formats.html; +import java.io.*; +import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.DeprecatedAPIListBuilder; import com.sun.tools.doclets.internal.toolkit.util.*; -import java.io.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Generate File to list all the deprecated classes and class members with the @@ -125,28 +127,21 @@ public class DeprecatedListWriter extends SubWriterHolderWriter { } /** - * Print the deprecated API list. Separately print all class kinds and - * member kinds. + * Generate the deprecated API list. * * @param deprapi list of deprecated API built already. */ protected void generateDeprecatedListFile(DeprecatedAPIListBuilder deprapi) - throws IOException { - writeHeader(); - - strong(configuration.getText("doclet.Contents")); - ul(); - for (int i = 0; i < DeprecatedAPIListBuilder.NUM_TYPES; i++) { - writeIndexLink(deprapi, i); - } - ulEnd(); - println(); - + throws IOException { + Content body = getHeader(); + body.addContent(getContentsList(deprapi)); String memberTableSummary; String[] memberTableHeader = new String[1]; + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.contentContainer); for (int i = 0; i < DeprecatedAPIListBuilder.NUM_TYPES; i++) { if (deprapi.hasDocumentation(i)) { - writeAnchor(deprapi, i); + addAnchor(deprapi, i, div); memberTableSummary = configuration.getText("doclet.Member_Table_Summary", configuration.getText(HEADING_KEYS[i]), @@ -154,66 +149,87 @@ public class DeprecatedListWriter extends SubWriterHolderWriter { memberTableHeader[0] = configuration.getText("doclet.0_and_1", configuration.getText(HEADER_KEYS[i]), configuration.getText("doclet.Description")); - writers[i].printDeprecatedAPI(deprapi.getList(i), - HEADING_KEYS[i], memberTableSummary, memberTableHeader); + writers[i].addDeprecatedAPI(deprapi.getList(i), + HEADING_KEYS[i], memberTableSummary, memberTableHeader, div); } } - printDeprecatedFooter(); + body.addContent(div); + addNavLinks(false, body); + addBottom(body); + printHtmlDocument(null, true, body); } - private void writeIndexLink(DeprecatedAPIListBuilder builder, - int type) { + /** + * Add the index link. + * + * @param builder the deprecated list builder + * @param type the type of list being documented + * @param contentTree the content tree to which the index link will be added + */ + private void addIndexLink(DeprecatedAPIListBuilder builder, + int type, Content contentTree) { if (builder.hasDocumentation(type)) { - li(); - printHyperLink("#" + ANCHORS[type], - configuration.getText(HEADING_KEYS[type])); - println(); - } - } - - private void writeAnchor(DeprecatedAPIListBuilder builder, int type) { - if (builder.hasDocumentation(type)) { - anchor(ANCHORS[type]); + Content li = HtmlTree.LI(getHyperLink("#" + ANCHORS[type], + getResource(HEADING_KEYS[type]))); + contentTree.addContent(li); } } /** - * Print the navigation bar and header for the deprecated API Listing. + * Get the contents list. + * + * @param deprapi the deprecated list builder + * @return a content tree for the contents list */ - protected void writeHeader() { - printHtmlHeader(configuration.getText("doclet.Window_Deprecated_List"), - null, true); - printTop(); - navLinks(true); - hr(); - center(); - h2(); - strongText("doclet.Deprecated_API"); - h2End(); - centerEnd(); - - hr(4, "noshade"); + public Content getContentsList(DeprecatedAPIListBuilder deprapi) { + Content headContent = getResource("doclet.Deprecated_API"); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.title, headContent); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + Content headingContent = getResource("doclet.Contents"); + div.addContent(HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, true, + headingContent)); + Content ul = new HtmlTree(HtmlTag.UL); + for (int i = 0; i < DeprecatedAPIListBuilder.NUM_TYPES; i++) { + addIndexLink(deprapi, i, ul); + } + div.addContent(ul); + return div; } /** - * Print the navigation bar and the footer for the deprecated API Listing. + * Add the anchor. + * + * @param builder the deprecated list builder + * @param type the type of list being documented + * @param contentTree the content tree to which the anchor will be added */ - protected void printDeprecatedFooter() { - hr(); - navLinks(false); - printBottom(); - printBodyHtmlEnd(); + private void addAnchor(DeprecatedAPIListBuilder builder, int type, Content htmlTree) { + if (builder.hasDocumentation(type)) { + htmlTree.addContent(getMarkerAnchor(ANCHORS[type])); + } } /** - * Highlight the word "Deprecated" in the navigation bar as this is the same - * page. + * Get the header for the deprecated API Listing. + * + * @return a content tree for the header */ - protected void navLinkDeprecated() { - navCellRevStart(); - fontStyle("NavBarFont1Rev"); - strongText("doclet.navDeprecated"); - fontEnd(); - navCellEnd(); + public Content getHeader() { + String title = configuration.getText("doclet.Window_Deprecated_List"); + Content bodyTree = getBody(true, getWindowTitle(title)); + addTop(bodyTree); + addNavLinks(true, bodyTree); + return bodyTree; + } + + /** + * Get the deprecated label. + * + * @return a content tree for the deprecated label + */ + protected Content getNavLinkDeprecated() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, deprecatedLabel); + return li; } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java index afa63b4c492..aeebc35d969 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java @@ -28,6 +28,7 @@ package com.sun.tools.doclets.formats.html; import java.io.*; import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; @@ -40,8 +41,6 @@ import com.sun.tools.doclets.internal.toolkit.util.*; public class EnumConstantWriterImpl extends AbstractMemberWriter implements EnumConstantWriter, MemberSummaryWriter { - private boolean printedSummaryHeader = false; - public EnumConstantWriterImpl(SubWriterHolderWriter writer, ClassDoc classdoc) { super(writer, classdoc); @@ -52,136 +51,98 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter } /** - * Write the enum constant summary header for the given class. - * - * @param classDoc the class the summary belongs to. + * {@inheritDoc} */ - public void writeMemberSummaryHeader(ClassDoc classDoc) { - printedSummaryHeader = true; - writer.println(""); - writer.println(); - writer.printSummaryHeader(this, classDoc); - } - - /** - * Write the enum constant summary footer for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeMemberSummaryFooter(ClassDoc classDoc) { - writer.printSummaryFooter(this, classDoc); - } - - /** - * Write the inherited enum constant summary header for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeInheritedMemberSummaryHeader(ClassDoc classDoc) { - if(! printedSummaryHeader){ - //We don't want inherited summary to not be under heading. - writeMemberSummaryHeader(classDoc); - writeMemberSummaryFooter(classDoc); - printedSummaryHeader = true; - } - writer.printInheritedSummaryHeader(this, classDoc); + public Content getMemberSummaryHeader(ClassDoc classDoc, + Content memberSummaryTree) { + memberSummaryTree.addContent(HtmlConstants.START_OF_ENUM_CONSTANT_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, classDoc, memberTree); + return memberTree; } /** * {@inheritDoc} */ - public void writeInheritedMemberSummary(ClassDoc classDoc, - ProgramElementDoc enumConstant, boolean isFirst, boolean isLast) { - writer.printInheritedSummaryMember(this, classDoc, enumConstant, isFirst); - } - - /** - * Write the inherited enum constant summary footer for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeInheritedMemberSummaryFooter(ClassDoc classDoc) { - writer.printInheritedSummaryFooter(this, classDoc); + public Content getEnumConstantsDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree) { + memberDetailsTree.addContent(HtmlConstants.START_OF_ENUM_CONSTANT_DETAILS); + Content enumConstantsDetailsTree = writer.getMemberTreeHeader(); + enumConstantsDetailsTree.addContent(writer.getMarkerAnchor("enum_constant_detail")); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.enumConstantsDetailsLabel); + enumConstantsDetailsTree.addContent(heading); + return enumConstantsDetailsTree; } /** * {@inheritDoc} */ - public void writeHeader(ClassDoc classDoc, String header) { - writer.println(); - writer.println(""); - writer.println(); - writer.anchor("enum_constant_detail"); - writer.printTableHeadingBackground(header); - writer.println(); + public Content getEnumConstantsTreeHeader(FieldDoc enumConstant, + Content enumConstantsDetailsTree) { + enumConstantsDetailsTree.addContent( + writer.getMarkerAnchor(enumConstant.name())); + Content enumConstantsTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(enumConstant.name()); + enumConstantsTree.addContent(heading); + return enumConstantsTree; } /** * {@inheritDoc} */ - public void writeEnumConstantHeader(FieldDoc enumConstant, boolean isFirst) { - if (! isFirst) { - writer.printMemberHeader(); - writer.println(""); - } - writer.anchor(enumConstant.name()); - writer.h3(); - writer.print(enumConstant.name()); - writer.h3End(); - } - - /** - * {@inheritDoc} - */ - public void writeSignature(FieldDoc enumConstant) { - writer.pre(); - writer.writeAnnotationInfo(enumConstant); - printModifiers(enumConstant); - writer.printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, - enumConstant.type())); - print(' '); + public Content getSignature(FieldDoc enumConstant) { + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(enumConstant, pre); + addModifiers(enumConstant, pre); + Content enumConstantLink = new RawHtml(writer.getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, + enumConstant.type()))); + pre.addContent(enumConstantLink); + pre.addContent(" "); if (configuration().linksource) { - writer.printSrcLink(enumConstant, enumConstant.name()); + Content enumConstantName = new StringContent(enumConstant.name()); + writer.addSrcLink(enumConstant, enumConstantName, pre); } else { - strong(enumConstant.name()); + addName(enumConstant.name(), pre); } - writer.preEnd(); - assert !writer.getMemberDetailsListPrinted(); + return pre; } /** * {@inheritDoc} */ - public void writeDeprecated(FieldDoc enumConstant) { - printDeprecated(enumConstant); + public void addDeprecated(FieldDoc enumConstant, Content enumConstantsTree) { + addDeprecatedInfo(enumConstant, enumConstantsTree); } /** * {@inheritDoc} */ - public void writeComments(FieldDoc enumConstant) { - printComment(enumConstant); + public void addComments(FieldDoc enumConstant, Content enumConstantsTree) { + addComment(enumConstant, enumConstantsTree); } /** * {@inheritDoc} */ - public void writeTags(FieldDoc enumConstant) { - writer.printTags(enumConstant); + public void addTags(FieldDoc enumConstant, Content enumConstantsTree) { + writer.addTagsInfo(enumConstant, enumConstantsTree); } /** * {@inheritDoc} */ - public void writeEnumConstantFooter() { - printMemberFooter(); + public Content getEnumConstantsDetails(Content enumConstantsDetailsTree) { + return getMemberTree(enumConstantsDetailsTree); } /** * {@inheritDoc} */ - public void writeFooter(ClassDoc classDoc) { - //No footer to write for enum constant documentation + public Content getEnumConstants(Content enumConstantsTree, + boolean isLastContent) { + return getMemberTree(enumConstantsTree, isLastContent); } /** @@ -195,75 +156,127 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter return VisibleMemberMap.ENUM_CONSTANTS; } - public void printSummaryLabel() { - writer.printText("doclet.Enum_Constant_Summary"); + /** + * {@inheritDoc} + */ + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Enum_Constant_Summary")); + memberTree.addContent(label); } - public void printTableSummary() { - writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + /** + * {@inheritDoc} + */ + public String getTableSummary() { + return configuration().getText("doclet.Member_Table_Summary", configuration().getText("doclet.Enum_Constant_Summary"), - configuration().getText("doclet.enum_constants"))); + configuration().getText("doclet.enum_constants")); } - public void printSummaryTableHeader(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + public String getCaption() { + return configuration().getText("doclet.Enum_Constants"); + } + + /** + * {@inheritDoc} + */ + public String[] getSummaryTableHeader(ProgramElementDoc member) { String[] header = new String[] { configuration().getText("doclet.0_and_1", configuration().getText("doclet.Enum_Constant"), configuration().getText("doclet.Description")) }; - writer.summaryTableHeader(header, "col"); + return header; } - public void printSummaryAnchor(ClassDoc cd) { - writer.anchor("enum_constant_summary"); + /** + * {@inheritDoc} + */ + public void addSummaryAnchor(ClassDoc cd, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor("enum_constant_summary")); } - public void printInheritedSummaryAnchor(ClassDoc cd) { - } // no such - - public void printInheritedSummaryLabel(ClassDoc cd) { - // no such + /** + * {@inheritDoc} + */ + public void addInheritedSummaryAnchor(ClassDoc cd, Content inheritedTree) { } - protected void writeSummaryLink(int context, ClassDoc cd, ProgramElementDoc member) { - writer.strong(); - writer.printDocLink(context, (MemberDoc) member, member.name(), false); - writer.strongEnd(); + /** + * {@inheritDoc} + */ + public void addInheritedSummaryLabel(ClassDoc cd, Content inheritedTree) { } - protected void writeInheritedSummaryLink(ClassDoc cd, - ProgramElementDoc member) { - writer.printDocLink(LinkInfoImpl.CONTEXT_MEMBER, (MemberDoc)member, - member.name(), false); + /** + * {@inheritDoc} + */ + protected void addSummaryLink(int context, ClassDoc cd, ProgramElementDoc member, + Content tdSummary) { + Content strong = HtmlTree.STRONG(new RawHtml( + writer.getDocLink(context, (MemberDoc) member, member.name(), false))); + Content code = HtmlTree.CODE(strong); + tdSummary.addContent(code); } - protected void printSummaryType(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + @Override + public void setSummaryColumnStyle(HtmlTree tdTree) { + tdTree.addStyle(HtmlStyle.colOne); + } + + /** + * {@inheritDoc} + */ + protected void addInheritedSummaryLink(ClassDoc cd, + ProgramElementDoc member, Content linksTree) { + } + + /** + * {@inheritDoc} + */ + protected void addSummaryType(ProgramElementDoc member, Content tdSummaryType) { //Not applicable. } - protected void writeDeprecatedLink(ProgramElementDoc member) { - writer.printDocLink(LinkInfoImpl.CONTEXT_MEMBER, - (MemberDoc) member, ((FieldDoc)member).qualifiedName(), false); + /** + * {@inheritDoc} + */ + protected Content getDeprecatedLink(ProgramElementDoc member) { + return writer.getDocLink(LinkInfoImpl.CONTEXT_MEMBER, + (MemberDoc) member, ((FieldDoc)member).qualifiedName()); } - protected void printNavSummaryLink(ClassDoc cd, boolean link) { + /** + * {@inheritDoc} + */ + protected Content getNavSummaryLink(ClassDoc cd, boolean link) { if (link) { - writer.printHyperLink("", (cd == null)? - "enum_constant_summary": - "enum_constants_inherited_from_class_" + - configuration().getClassName(cd), - configuration().getText("doclet.navEnum")); + return writer.getHyperLink("", (cd == null)? + "enum_constant_summary": + "enum_constants_inherited_from_class_" + + configuration().getClassName(cd), + writer.getResource("doclet.navEnum")); } else { - writer.printText("doclet.navEnum"); + return writer.getResource("doclet.navEnum"); } } - protected void printNavDetailLink(boolean link) { + /** + * {@inheritDoc} + */ + protected void addNavDetailLink(boolean link, Content liNav) { if (link) { - writer.printHyperLink("", "enum_constant_detail", - configuration().getText("doclet.navEnum")); + liNav.addContent(writer.getHyperLink("", "enum_constant_detail", + writer.getResource("doclet.navEnum"))); } else { - writer.printText("doclet.navEnum"); + liNav.addContent(writer.getResource("doclet.navEnum")); } } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java index 6d9cc1aa65b..bc2ccfb7b57 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java @@ -28,6 +28,7 @@ package com.sun.tools.doclets.formats.html; import java.io.*; import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; @@ -42,8 +43,6 @@ import com.sun.tools.doclets.internal.toolkit.util.*; public class FieldWriterImpl extends AbstractMemberWriter implements FieldWriter, MemberSummaryWriter { - private boolean printedSummaryHeader = false; - public FieldWriterImpl(SubWriterHolderWriter writer, ClassDoc classdoc) { super(writer, classdoc); } @@ -53,177 +52,118 @@ public class FieldWriterImpl extends AbstractMemberWriter } /** - * Write the fields summary header for the given class. - * - * @param classDoc the class the summary belongs to. + * {@inheritDoc} */ - public void writeMemberSummaryHeader(ClassDoc classDoc) { - printedSummaryHeader = true; - writer.println(""); - writer.println(); - writer.printSummaryHeader(this, classDoc); - } - - /** - * Write the fields summary footer for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeMemberSummaryFooter(ClassDoc classDoc) { - writer.tableEnd(); - writer.space(); - } - - /** - * Write the inherited fields summary header for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeInheritedMemberSummaryHeader(ClassDoc classDoc) { - if(! printedSummaryHeader){ - //We don't want inherited summary to not be under heading. - writeMemberSummaryHeader(classDoc); - writeMemberSummaryFooter(classDoc); - printedSummaryHeader = true; - } - writer.printInheritedSummaryHeader(this, classDoc); + public Content getMemberSummaryHeader(ClassDoc classDoc, + Content memberSummaryTree) { + memberSummaryTree.addContent(HtmlConstants.START_OF_FIELD_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, classDoc, memberTree); + return memberTree; } /** * {@inheritDoc} */ - public void writeInheritedMemberSummary(ClassDoc classDoc, - ProgramElementDoc field, boolean isFirst, boolean isLast) { - writer.printInheritedSummaryMember(this, classDoc, field, isFirst); + public Content getFieldDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree) { + memberDetailsTree.addContent(HtmlConstants.START_OF_FIELD_DETAILS); + Content fieldDetailsTree = writer.getMemberTreeHeader(); + fieldDetailsTree.addContent(writer.getMarkerAnchor("field_detail")); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.fieldDetailsLabel); + fieldDetailsTree.addContent(heading); + return fieldDetailsTree; } /** - * Write the inherited fields summary footer for the given class. - * - * @param classDoc the class the summary belongs to. + * {@inheritDoc} */ - public void writeInheritedMemberSummaryFooter(ClassDoc classDoc) { - writer.printInheritedSummaryFooter(this, classDoc); + public Content getFieldDocTreeHeader(FieldDoc field, + Content fieldDetailsTree) { + fieldDetailsTree.addContent( + writer.getMarkerAnchor(field.name())); + Content fieldDocTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(field.name()); + fieldDocTree.addContent(heading); + return fieldDocTree; } /** - * Write the header for the field documentation. - * - * @param classDoc the class that the fields belong to. + * {@inheritDoc} */ - public void writeHeader(ClassDoc classDoc, String header) { - writer.println(); - writer.println(""); - writer.println(); - writer.anchor("field_detail"); - writer.printTableHeadingBackground(header); - writer.println(); - } - - /** - * Write the field header for the given field. - * - * @param field the field being documented. - * @param isFirst the flag to indicate whether or not the field is the - * first to be documented. - */ - public void writeFieldHeader(FieldDoc field, boolean isFirst) { - if (! isFirst) { - writer.printMemberHeader(); - writer.println(""); - } - writer.anchor(field.name()); - writer.h3(); - writer.print(field.name()); - writer.h3End(); - } - - /** - * Write the signature for the given field. - * - * @param field the field being documented. - */ - public void writeSignature(FieldDoc field) { - writer.pre(); - writer.writeAnnotationInfo(field); - printModifiers(field); - writer.printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, - field.type())); - print(' '); + public Content getSignature(FieldDoc field) { + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(field, pre); + addModifiers(field, pre); + Content fieldlink = new RawHtml(writer.getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, + field.type()))); + pre.addContent(fieldlink); + pre.addContent(" "); if (configuration().linksource) { - writer.printSrcLink(field, field.name()); + Content fieldName = new StringContent(field.name()); + writer.addSrcLink(field, fieldName, pre); } else { - strong(field.name()); + addName(field.name(), pre); } - writer.preEnd(); - assert !writer.getMemberDetailsListPrinted(); + return pre; } /** - * Write the deprecated output for the given field. - * - * @param field the field being documented. + * {@inheritDoc} */ - public void writeDeprecated(FieldDoc field) { - printDeprecated(field); + public void addDeprecated(FieldDoc field, Content fieldDocTree) { + addDeprecatedInfo(field, fieldDocTree); } /** - * Write the comments for the given field. - * - * @param field the field being documented. + * {@inheritDoc} */ - public void writeComments(FieldDoc field) { + public void addComments(FieldDoc field, Content fieldDocTree) { ClassDoc holder = field.containingClass(); if (field.inlineTags().length > 0) { - writer.printMemberDetailsListStartTag(); if (holder.equals(classdoc) || - (! (holder.isPublic() || Util.isLinkable(holder, configuration())))) { - writer.dd(); - writer.printInlineComment(field); - writer.ddEnd(); + (! (holder.isPublic() || Util.isLinkable(holder, configuration())))) { + writer.addInlineComment(field, fieldDocTree); } else { - String classlink = writer.codeText( - writer.getDocLink(LinkInfoImpl.CONTEXT_FIELD_DOC_COPY, + Content link = new RawHtml( + writer.getDocLink(LinkInfoImpl.CONTEXT_FIELD_DOC_COPY, holder, field, holder.isIncluded() ? holder.typeName() : holder.qualifiedTypeName(), - false)); - writer.dd(); - writer.strong(configuration().getText(holder.isClass()? - "doclet.Description_From_Class" : - "doclet.Description_From_Interface", classlink)); - writer.ddEnd(); - writer.dd(); - writer.printInlineComment(field); - writer.ddEnd(); + false)); + Content codeLink = HtmlTree.CODE(link); + Content strong = HtmlTree.STRONG(holder.isClass()? + writer.descfrmClassLabel : writer.descfrmInterfaceLabel); + strong.addContent(writer.getSpace()); + strong.addContent(codeLink); + fieldDocTree.addContent(HtmlTree.DIV(HtmlStyle.block, strong)); + writer.addInlineComment(field, fieldDocTree); } } } /** - * Write the tag output for the given field. - * - * @param field the field being documented. + * {@inheritDoc} */ - public void writeTags(FieldDoc field) { - writer.printTags(field); + public void addTags(FieldDoc field, Content fieldDocTree) { + writer.addTagsInfo(field, fieldDocTree); } /** - * Write the field footer. + * {@inheritDoc} */ - public void writeFieldFooter() { - printMemberFooter(); + public Content getFieldDetails(Content fieldDetailsTree) { + return getMemberTree(fieldDetailsTree); } /** - * Write the footer for the field documentation. - * - * @param classDoc the class that the fields belong to. + * {@inheritDoc} */ - public void writeFooter(ClassDoc classDoc) { - //No footer to write for field documentation + public Content getFieldDoc(Content fieldDocTree, + boolean isLastContent) { + return getMemberTree(fieldDocTree, isLastContent); } /** @@ -237,85 +177,136 @@ public class FieldWriterImpl extends AbstractMemberWriter return VisibleMemberMap.FIELDS; } - public void printSummaryLabel() { - writer.printText("doclet.Field_Summary"); + /** + * {@inheritDoc} + */ + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Field_Summary")); + memberTree.addContent(label); } - public void printTableSummary() { - writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + /** + * {@inheritDoc} + */ + public String getTableSummary() { + return configuration().getText("doclet.Member_Table_Summary", configuration().getText("doclet.Field_Summary"), - configuration().getText("doclet.fields"))); + configuration().getText("doclet.fields")); } - public void printSummaryTableHeader(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + public String getCaption() { + return configuration().getText("doclet.Fields"); + } + + /** + * {@inheritDoc} + */ + public String[] getSummaryTableHeader(ProgramElementDoc member) { String[] header = new String[] { writer.getModifierTypeHeader(), configuration().getText("doclet.0_and_1", configuration().getText("doclet.Field"), configuration().getText("doclet.Description")) }; - writer.summaryTableHeader(header, "col"); + return header; } - public void printSummaryAnchor(ClassDoc cd) { - writer.anchor("field_summary"); + /** + * {@inheritDoc} + */ + public void addSummaryAnchor(ClassDoc cd, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor("field_summary")); } - public void printInheritedSummaryAnchor(ClassDoc cd) { - writer.anchor("fields_inherited_from_class_" + configuration().getClassName(cd)); + /** + * {@inheritDoc} + */ + public void addInheritedSummaryAnchor(ClassDoc cd, Content inheritedTree) { + inheritedTree.addContent(writer.getMarkerAnchor( + "fields_inherited_from_class_" + configuration().getClassName(cd))); } - public void printInheritedSummaryLabel(ClassDoc cd) { - String classlink = writer.getPreQualifiedClassLink( - LinkInfoImpl.CONTEXT_MEMBER, cd, false); - writer.strong(); - String key = cd.isClass()? - "doclet.Fields_Inherited_From_Class" : - "doclet.Fields_Inherited_From_Interface"; - writer.printText(key, classlink); - writer.strongEnd(); + /** + * {@inheritDoc} + */ + public void addInheritedSummaryLabel(ClassDoc cd, Content inheritedTree) { + Content classLink = new RawHtml(writer.getPreQualifiedClassLink( + LinkInfoImpl.CONTEXT_MEMBER, cd, false)); + Content label = new StringContent(cd.isClass() ? + configuration().getText("doclet.Fields_Inherited_From_Class") : + configuration().getText("doclet.Fields_Inherited_From_Interface")); + Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING, + label); + labelHeading.addContent(writer.getSpace()); + labelHeading.addContent(classLink); + inheritedTree.addContent(labelHeading); } - protected void writeSummaryLink(int context, ClassDoc cd, ProgramElementDoc member) { - writer.strong(); - writer.printDocLink(context, cd , (MemberDoc) member, member.name(), false); - writer.strongEnd(); + /** + * {@inheritDoc} + */ + protected void addSummaryLink(int context, ClassDoc cd, ProgramElementDoc member, + Content tdSummary) { + Content strong = HtmlTree.STRONG(new RawHtml( + writer.getDocLink(context, cd , (MemberDoc) member, member.name(), false))); + Content code = HtmlTree.CODE(strong); + tdSummary.addContent(code); } - protected void writeInheritedSummaryLink(ClassDoc cd, - ProgramElementDoc member) { - writer.printDocLink(LinkInfoImpl.CONTEXT_MEMBER, cd, (MemberDoc)member, - member.name(), false); + /** + * {@inheritDoc} + */ + protected void addInheritedSummaryLink(ClassDoc cd, + ProgramElementDoc member, Content linksTree) { + linksTree.addContent(new RawHtml( + writer.getDocLink(LinkInfoImpl.CONTEXT_MEMBER, cd, (MemberDoc)member, + member.name(), false))); } - protected void printSummaryType(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + protected void addSummaryType(ProgramElementDoc member, Content tdSummaryType) { FieldDoc field = (FieldDoc)member; - printModifierAndType(field, field.type()); + addModifierAndType(field, field.type(), tdSummaryType); } - protected void writeDeprecatedLink(ProgramElementDoc member) { - writer.printDocLink(LinkInfoImpl.CONTEXT_MEMBER, - (MemberDoc) member, ((FieldDoc)member).qualifiedName(), false); + /** + * {@inheritDoc} + */ + protected Content getDeprecatedLink(ProgramElementDoc member) { + return writer.getDocLink(LinkInfoImpl.CONTEXT_MEMBER, + (MemberDoc) member, ((FieldDoc)member).qualifiedName()); } - protected void printNavSummaryLink(ClassDoc cd, boolean link) { + /** + * {@inheritDoc} + */ + protected Content getNavSummaryLink(ClassDoc cd, boolean link) { if (link) { - writer.printHyperLink("", (cd == null)? - "field_summary": - "fields_inherited_from_class_" + - configuration().getClassName(cd), - configuration().getText("doclet.navField")); + return writer.getHyperLink("", (cd == null)? + "field_summary": + "fields_inherited_from_class_" + + configuration().getClassName(cd), + writer.getResource("doclet.navField")); } else { - writer.printText("doclet.navField"); + return writer.getResource("doclet.navField"); } } - protected void printNavDetailLink(boolean link) { + /** + * {@inheritDoc} + */ + protected void addNavDetailLink(boolean link, Content liNav) { if (link) { - writer.printHyperLink("", "field_detail", - configuration().getText("doclet.navField")); + liNav.addContent(writer.getHyperLink("", "field_detail", + writer.getResource("doclet.navField"))); } else { - writer.printText("doclet.navField"); + liNav.addContent(writer.getResource("doclet.navField")); } } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java index 9d11d9e262e..e24d7c47240 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java @@ -25,8 +25,10 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.util.*; import java.io.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Generate the documentation in the Html "frame" format in the browser. The @@ -47,6 +49,8 @@ public class FrameOutputWriter extends HtmlDocletWriter { */ int noOfPackages; + private final String SCROLL_YES = "yes"; + /** * Constructor to construct FrameOutputWriter object. * @@ -86,82 +90,93 @@ public class FrameOutputWriter extends HtmlDocletWriter { * as well as warning if browser is not supporting the Html frames. */ protected void generateFrameFile() { + Content frameset = getFrameDetails(); if (configuration.windowtitle.length() > 0) { - printFramesetHeader(configuration.windowtitle, configuration.notimestamp); + printFramesetDocument(configuration.windowtitle, configuration.notimestamp, + frameset); } else { - printFramesetHeader(configuration.getText("doclet.Generated_Docs_Untitled"), - configuration.notimestamp); + printFramesetDocument(configuration.getText("doclet.Generated_Docs_Untitled"), + configuration.notimestamp, frameset); } - printFrameDetails(); - printFrameFooter(); } /** - * Generate the code for issueing the warning for a non-frame capable web + * Add the code for issueing the warning for a non-frame capable web * client. Also provide links to the non-frame version documentation. + * + * @param contentTree the content tree to which the non-frames information will be added */ - protected void printFrameWarning() { - noFrames(); - h2(); - printText("doclet.Frame_Alert"); - h2End(); - p(); - printText("doclet.Frame_Warning_Message"); - br(); - printText("doclet.Link_To"); - printHyperLink(configuration.topFile, - configuration.getText("doclet.Non_Frame_Version")); - println(""); - noFramesEnd(); + protected void addFrameWarning(Content contentTree) { + Content noframes = new HtmlTree(HtmlTag.NOFRAMES); + Content noScript = HtmlTree.NOSCRIPT( + HtmlTree.DIV(getResource("doclet.No_Script_Message"))); + noframes.addContent(noScript); + Content noframesHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Frame_Alert")); + noframes.addContent(noframesHead); + Content p = HtmlTree.P(getResource("doclet.Frame_Warning_Message")); + noframes.addContent(p); + noframes.addContent(new HtmlTree(HtmlTag.BR)); + noframes.addContent(getResource("doclet.Link_To")); + Content link = getHyperLink(configuration.topFile, + getResource("doclet.Non_Frame_Version")); + noframes.addContent(link); + contentTree.addContent(noframes); } /** - * Print the frame sizes and their contents. + * Get the frame sizes and their contents. + * + * @return a content tree for the frame details */ - protected void printFrameDetails() { - // title attribute intentionally made empty so - // 508 tests will not flag it as missing - frameSet("cols=\"20%,80%\" title=\"\" onLoad=\"top.loadFrames()\""); + protected Content getFrameDetails() { + HtmlTree frameset = HtmlTree.FRAMESET("20%,80%", null, "Documentation frame", + "top.loadFrames()"); if (noOfPackages <= 1) { - printAllClassesFrameTag(); + addAllClassesFrameTag(frameset); } else if (noOfPackages > 1) { - frameSet("rows=\"30%,70%\" title=\"\" onLoad=\"top.loadFrames()\""); - printAllPackagesFrameTag(); - printAllClassesFrameTag(); - frameSetEnd(); + HtmlTree leftFrameset = HtmlTree.FRAMESET(null, "30%,70%", "Left frames", + "top.loadFrames()"); + addAllPackagesFrameTag(leftFrameset); + addAllClassesFrameTag(leftFrameset); + frameset.addContent(leftFrameset); } - printClassFrameTag(); - printFrameWarning(); - frameSetEnd(); + addClassFrameTag(frameset); + addFrameWarning(frameset); + return frameset; } /** - * Print the FRAME tag for the frame that lists all packages + * Add the FRAME tag for the frame that lists all packages. + * + * @param contentTree the content tree to which the information will be added */ - private void printAllPackagesFrameTag() { - frame("src=\"overview-frame.html\" name=\"packageListFrame\"" - + " title=\"" + configuration.getText("doclet.All_Packages") + "\""); + private void addAllPackagesFrameTag(Content contentTree) { + HtmlTree frame = HtmlTree.FRAME("overview-frame.html", "packageListFrame", + configuration.getText("doclet.All_Packages")); + contentTree.addContent(frame); } /** - * Print the FRAME tag for the frame that lists all classes + * Add the FRAME tag for the frame that lists all classes. + * + * @param contentTree the content tree to which the information will be added */ - private void printAllClassesFrameTag() { - frame("src=\"" + "allclasses-frame.html" + "\"" - + " name=\"packageFrame\"" - + " title=\"" + configuration.getText("doclet.All_classes_and_interfaces") - + "\""); + private void addAllClassesFrameTag(Content contentTree) { + HtmlTree frame = HtmlTree.FRAME("allclasses-frame.html", "packageFrame", + configuration.getText("doclet.All_classes_and_interfaces")); + contentTree.addContent(frame); } /** - * Print the FRAME tag for the frame that describes the class in detail + * Add the FRAME tag for the frame that describes the class in detail. + * + * @param contentTree the content tree to which the information will be added */ - private void printClassFrameTag() { - frame("src=\"" + configuration.topFile + "\"" - + " name=\"classFrame\"" - + " title=\"" - + configuration.getText("doclet.Package_class_and_interface_descriptions") - + "\" scrolling=\"yes\""); + private void addClassFrameTag(Content contentTree) { + HtmlTree frame = HtmlTree.FRAME(configuration.topFile, "classFrame", + configuration.getText("doclet.Package_class_and_interface_descriptions"), + SCROLL_YES); + contentTree.addContent(frame); } - } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java index 2c6eaca5941..832a7a6a932 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java @@ -25,8 +25,10 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.util.*; import java.io.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Generate the Help File for the generated API documentation. The help file @@ -72,159 +74,242 @@ public class HelpWriter extends HtmlDocletWriter { * Generate the help file contents. */ protected void generateHelpFile() { - printHtmlHeader(configuration.getText("doclet.Window_Help_title"), - null, true); - printTop(); - navLinks(true); hr(); - - printHelpFileContents(); - - navLinks(false); - printBottom(); - printBodyHtmlEnd(); + String title = configuration.getText("doclet.Window_Help_title"); + Content body = getBody(true, getWindowTitle(title)); + addTop(body); + addNavLinks(true, body); + addHelpFileContents(body); + addNavLinks(false, body); + addBottom(body); + printHtmlDocument(null, true, body); } /** - * Print the help file contents from the resource file. While generating the + * Add the help file contents from the resource file to the content tree. While adding the * help file contents it also keeps track of user options. If "-notree" - * is used, then the "overview-tree.html" will not get generated and hence - * help information also will not get generated. + * is used, then the "overview-tree.html" will not get added and hence + * help information also will not get added. + * + * @param contentTree the content tree to which the help file contents will be added */ - protected void printHelpFileContents() { - center(); h1(); printText("doclet.Help_line_1"); h1End(); centerEnd(); - printText("doclet.Help_line_2"); + protected void addHelpFileContents(Content contentTree) { + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, false, HtmlStyle.title, + getResource("doclet.Help_line_1")); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + Content line2 = HtmlTree.P(HtmlStyle.subTitle, + getResource("doclet.Help_line_2")); + div.addContent(line2); + contentTree.addContent(div); + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); if (configuration.createoverview) { - h3(); printText("doclet.Overview"); h3End(); - blockquote(); p(); - printText("doclet.Help_line_3", - getHyperLink("overview-summary.html", - configuration.getText("doclet.Overview"))); - blockquoteEnd(); + Content overviewHeading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Overview")); + Content liOverview = HtmlTree.LI(HtmlStyle.blockList, overviewHeading); + Content line3 = getResource("doclet.Help_line_3", + getHyperLinkString("overview-summary.html", + configuration.getText("doclet.Overview"))); + Content overviewPara = HtmlTree.P(line3); + liOverview.addContent(overviewPara); + ul.addContent(liOverview); } - h3(); printText("doclet.Package"); h3End(); - blockquote(); p(); printText("doclet.Help_line_4"); - ul(); - li(); printText("doclet.Interfaces_Italic"); - li(); printText("doclet.Classes"); - li(); printText("doclet.Enums"); - li(); printText("doclet.Exceptions"); - li(); printText("doclet.Errors"); - li(); printText("doclet.AnnotationTypes"); - ulEnd(); - blockquoteEnd(); - h3(); printText("doclet.Help_line_5"); h3End(); - blockquote(); p(); printText("doclet.Help_line_6"); - ul(); - li(); printText("doclet.Help_line_7"); - li(); printText("doclet.Help_line_8"); - li(); printText("doclet.Help_line_9"); - li(); printText("doclet.Help_line_10"); - li(); printText("doclet.Help_line_11"); - li(); printText("doclet.Help_line_12"); - p(); - li(); printText("doclet.Nested_Class_Summary"); - li(); printText("doclet.Field_Summary"); - li(); printText("doclet.Constructor_Summary"); - li(); printText("doclet.Method_Summary"); - p(); - li(); printText("doclet.Field_Detail"); - li(); printText("doclet.Constructor_Detail"); - li(); printText("doclet.Method_Detail"); - ulEnd(); - printText("doclet.Help_line_13"); - blockquoteEnd(); - + Content packageHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Package")); + Content liPackage = HtmlTree.LI(HtmlStyle.blockList, packageHead); + Content line4 = getResource("doclet.Help_line_4"); + Content packagePara = HtmlTree.P(line4); + liPackage.addContent(packagePara); + HtmlTree ulPackage = new HtmlTree(HtmlTag.UL); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.Interfaces_Italic"))); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.Classes"))); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.Enums"))); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.Exceptions"))); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.Errors"))); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.AnnotationTypes"))); + liPackage.addContent(ulPackage); + ul.addContent(liPackage); + Content classHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_5")); + Content liClass = HtmlTree.LI(HtmlStyle.blockList, classHead); + Content line6 = getResource("doclet.Help_line_6"); + Content classPara = HtmlTree.P(line6); + liClass.addContent(classPara); + HtmlTree ul1 = new HtmlTree(HtmlTag.UL); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_7"))); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_8"))); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_9"))); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_10"))); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_11"))); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_12"))); + liClass.addContent(ul1); + HtmlTree ul2 = new HtmlTree(HtmlTag.UL); + ul2.addContent(HtmlTree.LI( + getResource("doclet.Nested_Class_Summary"))); + ul2.addContent(HtmlTree.LI( + getResource("doclet.Field_Summary"))); + ul2.addContent(HtmlTree.LI( + getResource("doclet.Constructor_Summary"))); + ul2.addContent(HtmlTree.LI( + getResource("doclet.Method_Summary"))); + liClass.addContent(ul2); + HtmlTree ul3 = new HtmlTree(HtmlTag.UL); + ul3.addContent(HtmlTree.LI( + getResource("doclet.Field_Detail"))); + ul3.addContent(HtmlTree.LI( + getResource("doclet.Constructor_Detail"))); + ul3.addContent(HtmlTree.LI( + getResource("doclet.Method_Detail"))); + liClass.addContent(ul3); + Content line13 = getResource("doclet.Help_line_13"); + Content para = HtmlTree.P(line13); + liClass.addContent(para); + ul.addContent(liClass); //Annotation Types - blockquoteEnd(); - h3(); printText("doclet.AnnotationType"); h3End(); - blockquote(); p(); printText("doclet.Help_annotation_type_line_1"); - ul(); - li(); printText("doclet.Help_annotation_type_line_2"); - li(); printText("doclet.Help_annotation_type_line_3"); - li(); printText("doclet.Annotation_Type_Required_Member_Summary"); - li(); printText("doclet.Annotation_Type_Optional_Member_Summary"); - li(); printText("doclet.Annotation_Type_Member_Detail"); - ulEnd(); - blockquoteEnd(); - + Content aHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.AnnotationType")); + Content liAnnotation = HtmlTree.LI(HtmlStyle.blockList, aHead); + Content aline1 = getResource("doclet.Help_annotation_type_line_1"); + Content aPara = HtmlTree.P(aline1); + liAnnotation.addContent(aPara); + HtmlTree aul = new HtmlTree(HtmlTag.UL); + aul.addContent(HtmlTree.LI( + getResource("doclet.Help_annotation_type_line_2"))); + aul.addContent(HtmlTree.LI( + getResource("doclet.Help_annotation_type_line_3"))); + aul.addContent(HtmlTree.LI( + getResource("doclet.Annotation_Type_Required_Member_Summary"))); + aul.addContent(HtmlTree.LI( + getResource("doclet.Annotation_Type_Optional_Member_Summary"))); + aul.addContent(HtmlTree.LI( + getResource("doclet.Annotation_Type_Member_Detail"))); + liAnnotation.addContent(aul); + ul.addContent(liAnnotation); //Enums - blockquoteEnd(); - h3(); printText("doclet.Enum"); h3End(); - blockquote(); p(); printText("doclet.Help_enum_line_1"); - ul(); - li(); printText("doclet.Help_enum_line_2"); - li(); printText("doclet.Help_enum_line_3"); - li(); printText("doclet.Enum_Constant_Summary"); - li(); printText("doclet.Enum_Constant_Detail"); - ulEnd(); - blockquoteEnd(); - + Content enumHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Enum")); + Content liEnum = HtmlTree.LI(HtmlStyle.blockList, enumHead); + Content eline1 = getResource("doclet.Help_enum_line_1"); + Content enumPara = HtmlTree.P(eline1); + liEnum.addContent(enumPara); + HtmlTree eul = new HtmlTree(HtmlTag.UL); + eul.addContent(HtmlTree.LI( + getResource("doclet.Help_enum_line_2"))); + eul.addContent(HtmlTree.LI( + getResource("doclet.Help_enum_line_3"))); + eul.addContent(HtmlTree.LI( + getResource("doclet.Enum_Constant_Summary"))); + eul.addContent(HtmlTree.LI( + getResource("doclet.Enum_Constant_Detail"))); + liEnum.addContent(eul); + ul.addContent(liEnum); if (configuration.classuse) { - h3(); printText("doclet.Help_line_14"); h3End(); - blockquote(); - printText("doclet.Help_line_15"); - blockquoteEnd(); + Content useHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_14")); + Content liUse = HtmlTree.LI(HtmlStyle.blockList, useHead); + Content line15 = getResource("doclet.Help_line_15"); + Content usePara = HtmlTree.P(line15); + liUse.addContent(usePara); + ul.addContent(liUse); } if (configuration.createtree) { - h3(); printText("doclet.Help_line_16"); h3End(); - blockquote(); - printText("doclet.Help_line_17_with_tree_link", - getHyperLink("overview-tree.html", - configuration.getText("doclet.Class_Hierarchy"))); - ul(); - li(); printText("doclet.Help_line_18"); - li(); printText("doclet.Help_line_19"); - ulEnd(); - blockquoteEnd(); + Content treeHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_16")); + Content liTree = HtmlTree.LI(HtmlStyle.blockList, treeHead); + Content line17 = getResource("doclet.Help_line_17_with_tree_link", + getHyperLinkString("overview-tree.html", + configuration.getText("doclet.Class_Hierarchy"))); + Content treePara = HtmlTree.P(line17); + liTree.addContent(treePara); + HtmlTree tul = new HtmlTree(HtmlTag.UL); + tul.addContent(HtmlTree.LI( + getResource("doclet.Help_line_18"))); + tul.addContent(HtmlTree.LI( + getResource("doclet.Help_line_19"))); + liTree.addContent(tul); + ul.addContent(liTree); } if (!(configuration.nodeprecatedlist || configuration.nodeprecated)) { - h3(); printText("doclet.Deprecated_API"); h3End(); - blockquote(); - printText("doclet.Help_line_20_with_deprecated_api_link", - getHyperLink("deprecated-list.html", - configuration.getText("doclet.Deprecated_API"))); - blockquoteEnd(); + Content dHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Deprecated_API")); + Content liDeprecated = HtmlTree.LI(HtmlStyle.blockList, dHead); + Content line20 = getResource("doclet.Help_line_20_with_deprecated_api_link", + getHyperLinkString("deprecated-list.html", + configuration.getText("doclet.Deprecated_API"))); + Content dPara = HtmlTree.P(line20); + liDeprecated.addContent(dPara); + ul.addContent(liDeprecated); } if (configuration.createindex) { String indexlink; if (configuration.splitindex) { - indexlink = getHyperLink("index-files/index-1.html", - configuration.getText("doclet.Index")); + indexlink = getHyperLinkString("index-files/index-1.html", + configuration.getText("doclet.Index")); } else { - indexlink = getHyperLink("index-all.html", - configuration.getText("doclet.Index")); + indexlink = getHyperLinkString("index-all.html", + configuration.getText("doclet.Index")); } - h3(); printText("doclet.Help_line_21"); h3End(); - blockquote(); - printText("doclet.Help_line_22", indexlink); - blockquoteEnd(); + Content indexHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_21")); + Content liIndex = HtmlTree.LI(HtmlStyle.blockList, indexHead); + Content line22 = getResource("doclet.Help_line_22", indexlink); + Content indexPara = HtmlTree.P(line22); + liIndex.addContent(indexPara); + ul.addContent(liIndex); } - h3(); printText("doclet.Help_line_23"); h3End(); - printText("doclet.Help_line_24"); - h3(); printText("doclet.Help_line_25"); h3End(); - printText("doclet.Help_line_26"); p(); - - h3(); printText("doclet.Serialized_Form"); h3End(); - printText("doclet.Help_line_27"); p(); - - h3(); printText("doclet.Constants_Summary"); h3End(); - printText("doclet.Help_line_28"); p(); - - font("-1"); em(); - printText("doclet.Help_line_29"); - emEnd(); fontEnd(); br(); - hr(); + Content prevHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_23")); + Content liPrev = HtmlTree.LI(HtmlStyle.blockList, prevHead); + Content line24 = getResource("doclet.Help_line_24"); + Content prevPara = HtmlTree.P(line24); + liPrev.addContent(prevPara); + ul.addContent(liPrev); + Content frameHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_25")); + Content liFrame = HtmlTree.LI(HtmlStyle.blockList, frameHead); + Content line26 = getResource("doclet.Help_line_26"); + Content framePara = HtmlTree.P(line26); + liFrame.addContent(framePara); + ul.addContent(liFrame); + Content sHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Serialized_Form")); + Content liSerial = HtmlTree.LI(HtmlStyle.blockList, sHead); + Content line27 = getResource("doclet.Help_line_27"); + Content serialPara = HtmlTree.P(line27); + liSerial.addContent(serialPara); + ul.addContent(liSerial); + Content constHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Constants_Summary")); + Content liConst = HtmlTree.LI(HtmlStyle.blockList, constHead); + Content line28 = getResource("doclet.Help_line_28"); + Content constPara = HtmlTree.P(line28); + liConst.addContent(constPara); + ul.addContent(liConst); + Content divContent = HtmlTree.DIV(HtmlStyle.contentContainer, ul); + Content line29 = HtmlTree.EM(getResource("doclet.Help_line_29")); + divContent.addContent(line29); + contentTree.addContent(divContent); } /** - * Highlight the word "Help" in the navigation bar as this is the help file. + * Get the help label. + * + * @return a content tree for the help label */ - protected void navLinkHelp() { - navCellRevStart(); - fontStyle("NavBarFont1Rev"); - strongText("doclet.Help"); - fontEnd(); - navCellEnd(); + protected Content getNavLinkHelp() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, helpLabel); + return li; } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java index b70fc9792be..d9c4627389c 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java @@ -144,8 +144,11 @@ public class HtmlDoclet extends AbstractDoclet { !configuration.nohelp) { HelpWriter.generate(configuration); } + // If a stylesheet file is not specified, copy the default stylesheet. if (configuration.stylesheetfile.length() == 0) { - StylesheetWriter.generate(configuration); + Util.copyFile(configuration, "stylesheet.css", Util.RESOURCESDIR, + (configdestdir.isEmpty()) ? + System.getProperty("user.dir") : configdestdir, false); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java index 5659f496efd..3259ecd1965 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java @@ -87,6 +87,11 @@ public class HtmlDocletWriter extends HtmlDocWriter { */ public ConfigurationImpl configuration; + /** + * To check whether annotation heading is printed or not. + */ + protected boolean printedAnnotationHeading = false; + /** * Constructor to construct the HtmlStandardWriter object. * @@ -169,7 +174,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { // Append slash if next character is not a slash if (relativepathNoSlash.length() > 0 && previndex < htmlstr.length() && htmlstr.charAt(previndex) != '/') { - buf.append(DirectoryManager.URL_FILE_SEPERATOR); + buf.append(DirectoryManager.URL_FILE_SEPARATOR); } } return buf.toString(); @@ -192,17 +197,47 @@ public class HtmlDocletWriter extends HtmlDocWriter { println(" "); scriptEnd(); noScript(); - println(" " + getHyperLink(link, where, label, strong, "", "", target)); + println(" " + getHyperLinkString(link, where, label, strong, "", "", target)); noScriptEnd(); println(DocletConstants.NL); } - private void printMethodInfo(MethodDoc method) { + /** + * Get the script to show or hide the All classes link. + * + * @param id id of the element to show or hide + * @return a content tree for the script + */ + public Content getAllClassesLinkScript(String id) { + HtmlTree script = new HtmlTree(HtmlTag.SCRIPT); + script.addAttr(HtmlAttr.TYPE, "text/javascript"); + String scriptCode = "\n"; + Content scriptContent = new RawHtml(scriptCode); + script.addContent(scriptContent); + Content div = HtmlTree.DIV(script); + return div; + } + + /** + * Add method information. + * + * @param method the method to be documented + * @param dl the content tree to which the method information will be added + */ + private void addMethodInfo(MethodDoc method, Content dl) { ClassDoc[] intfacs = method.containingClass().interfaces(); MethodDoc overriddenMethod = method.overriddenMethod(); // Check whether there is any implementation or overridden info to be @@ -211,46 +246,38 @@ public class HtmlDocletWriter extends HtmlDocWriter { if ((intfacs.length > 0 && new ImplementedMethods(method, this.configuration).build().length > 0) || overriddenMethod != null) { - printMemberDetailsListStartTag(); - dd(); - printTagsInfoHeader(); - MethodWriterImpl.printImplementsInfo(this, method); + MethodWriterImpl.addImplementsInfo(this, method, dl); if (overriddenMethod != null) { - MethodWriterImpl.printOverridden(this, - method.overriddenType(), overriddenMethod); + MethodWriterImpl.addOverridden(this, + method.overriddenType(), overriddenMethod, dl); } - printTagsInfoFooter(); - ddEnd(); } } - protected void printTags(Doc doc) { - if(configuration.nocomment){ + /** + * Adds the tags information. + * + * @param doc the doc for which the tags will be generated + * @param htmltree the documentation tree to which the tags will be added + */ + protected void addTagsInfo(Doc doc, Content htmltree) { + if (configuration.nocomment) { return; } + Content dl = new HtmlTree(HtmlTag.DL); if (doc instanceof MethodDoc) { - printMethodInfo((MethodDoc) doc); + addMethodInfo((MethodDoc) doc, dl); } TagletOutputImpl output = new TagletOutputImpl(""); TagletWriter.genTagOuput(configuration.tagletManager, doc, configuration.tagletManager.getCustomTags(doc), getTagletWriterInstance(false), output); String outputString = output.toString().trim(); - // For RootDoc, ClassDoc and PackageDoc, this section is not the - // definition description but the start of definition list. if (!outputString.isEmpty()) { - if (!(doc instanceof RootDoc || doc instanceof ClassDoc || - doc instanceof PackageDoc)) { - printMemberDetailsListStartTag(); - dd(); - } - printTagsInfoHeader(); - print(outputString); - printTagsInfoFooter(); - if (!(doc instanceof RootDoc || doc instanceof ClassDoc || - doc instanceof PackageDoc)) - ddEnd(); + Content resultString = new RawHtml(outputString); + dl.addContent(resultString); } + htmltree.addContent(dl); } /** @@ -286,17 +313,16 @@ public class HtmlDocletWriter extends HtmlDocWriter { } /** - * Print Package link, with target frame. + * Get Package link, with target frame. * - * @param pd The link will be to the "package-summary.html" page for this - * package. - * @param target Name of the target frame. - * @param label Tag for the link. + * @param pd The link will be to the "package-summary.html" page for this package + * @param target name of the target frame + * @param label tag for the link + * @return a content for the target package link */ - public void printTargetPackageLink(PackageDoc pd, String target, - String label) { - print(getHyperLink(pathString(pd, "package-summary.html"), "", label, - false, "", "", target)); + public Content getTargetPackageLink(PackageDoc pd, String target, + Content label) { + return getHyperLink(pathString(pd, "package-summary.html"), "", label, "", target); } /** @@ -359,6 +385,64 @@ public class HtmlDocletWriter extends HtmlDocWriter { body("white", includeScript); } + /** + * Generates the HTML document tree and prints it out. + * + * @param metakeywords Array of String keywords for META tag. Each element + * of the array is assigned to a separate META tag. + * Pass in null for no array + * @param includeScript true if printing windowtitle script + * false for files that appear in the left-hand frames + * @param body the body htmltree to be included in the document + */ + public void printHtmlDocument(String[] metakeywords, boolean includeScript, + Content body) { + Content htmlDocType = DocType.Transitional(); + Content htmlComment = new Comment(configuration.getText("doclet.New_Page")); + Content head = new HtmlTree(HtmlTag.HEAD); + if (!configuration.notimestamp) { + Content headComment = new Comment("Generated by javadoc (version " + + ConfigurationImpl.BUILD_DATE + ") on " + today()); + head.addContent(headComment); + } + if (configuration.charset.length() > 0) { + Content meta = HtmlTree.META("Content-Type", "text/html", + configuration.charset); + head.addContent(meta); + } + head.addContent(getTitle()); + if (!configuration.notimestamp) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + Content meta = HtmlTree.META("date", dateFormat.format(new Date())); + head.addContent(meta); + } + if (metakeywords != null) { + for (int i=0; i < metakeywords.length; i++) { + Content meta = HtmlTree.META("keywords", metakeywords[i]); + head.addContent(meta); + } + } + head.addContent(getStyleSheetProperties()); + Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), + head, body); + Content htmlDocument = new HtmlDocument(htmlDocType, + htmlComment, htmlTree); + print(htmlDocument.toString()); + } + + /** + * Get the window title. + * + * @param title the title string to construct the complete window title + * @return the window title string + */ + public String getWindowTitle(String title) { + if (configuration.windowtitle.length() > 0) { + title += " (" + configuration.windowtitle + ")"; + } + return title; + } + /** * Print user specified header and the footer. * @@ -379,6 +463,28 @@ public class HtmlDocletWriter extends HtmlDocWriter { emEnd(); } + /** + * Get user specified header and the footer. + * + * @param header if true print the user provided header else print the + * user provided footer. + */ + public Content getUserHeaderFooter(boolean header) { + String content; + if (header) { + content = replaceDocRootDir(configuration.header); + } else { + if (configuration.footer.length() != 0) { + content = replaceDocRootDir(configuration.footer); + } else { + content = replaceDocRootDir(configuration.header); + } + } + Content rawContent = new RawHtml(content); + Content em = HtmlTree.EM(rawContent); + return em; + } + /** * Print the user specified top. */ @@ -387,6 +493,16 @@ public class HtmlDocletWriter extends HtmlDocWriter { hr(); } + /** + * Adds the user specified top. + * + * @param body the content tree to which user specified top will be added + */ + public void addTop(Content body) { + Content top = new RawHtml(replaceDocRootDir(configuration.top)); + body.addContent(top); + } + /** * Print the user specified bottom. */ @@ -395,6 +511,18 @@ public class HtmlDocletWriter extends HtmlDocWriter { print(replaceDocRootDir(configuration.bottom)); } + /** + * Adds the user specified bottom. + * + * @param body the content tree to which user specified bottom will be added + */ + public void addBottom(Content body) { + Content bottom = new RawHtml(replaceDocRootDir(configuration.bottom)); + Content small = HtmlTree.SMALL(bottom); + Content p = HtmlTree.P(HtmlStyle.legalCopy, small); + body.addContent(p); + } + /** * Print the navigation bar for the Html page at the top and and the bottom. * @@ -408,13 +536,13 @@ public class HtmlDocletWriter extends HtmlDocWriter { println(DocletConstants.NL + ""); anchor("navbar_top"); println(); - print(getHyperLink("", "skip-navbar_top", "", false, "", + print(getHyperLinkString("", "skip-navbar_top", "", false, "", configuration.getText("doclet.Skip_navigation_links"), "")); } else { println(DocletConstants.NL + ""); anchor("navbar_bottom"); println(); - print(getHyperLink("", "skip-navbar_bottom", "", false, "", + print(getHyperLinkString("", "skip-navbar_bottom", "", false, "", configuration.getText("doclet.Skip_navigation_links"), "")); } table(0, "100%", 1, 0); @@ -517,6 +645,97 @@ public class HtmlDocletWriter extends HtmlDocWriter { } } + /** + * Adds the navigation bar for the Html page at the top and and the bottom. + * + * @param header If true print navigation bar at the top of the page else + * @param body the HtmlTree to which the nav links will be added + */ + protected void addNavLinks(boolean header, Content body) { + if (!configuration.nonavbar) { + String allClassesId = "allclasses_"; + HtmlTree navDiv = new HtmlTree(HtmlTag.DIV); + if (header) { + body.addContent(HtmlConstants.START_OF_TOP_NAVBAR); + navDiv.addStyle(HtmlStyle.topNav); + allClassesId += "navbar_top"; + Content a = getMarkerAnchor("navbar_top"); + navDiv.addContent(a); + Content skipLinkContent = getHyperLink("", + "skip-navbar_top", HtmlTree.EMPTY, configuration.getText( + "doclet.Skip_navigation_links"), ""); + navDiv.addContent(skipLinkContent); + } else { + body.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR); + navDiv.addStyle(HtmlStyle.bottomNav); + allClassesId += "navbar_bottom"; + Content a = getMarkerAnchor("navbar_bottom"); + navDiv.addContent(a); + Content skipLinkContent = getHyperLink("", + "skip-navbar_bottom", HtmlTree.EMPTY, configuration.getText( + "doclet.Skip_navigation_links"), ""); + navDiv.addContent(skipLinkContent); + } + if (header) { + navDiv.addContent(getMarkerAnchor("navbar_top_firstrow")); + } else { + navDiv.addContent(getMarkerAnchor("navbar_bottom_firstrow")); + } + HtmlTree navList = new HtmlTree(HtmlTag.UL); + navList.addStyle(HtmlStyle.navList); + navList.addAttr(HtmlAttr.TITLE, "Navigation"); + if (configuration.createoverview) { + navList.addContent(getNavLinkContents()); + } + if (configuration.packages.length == 1) { + navList.addContent(getNavLinkPackage(configuration.packages[0])); + } else if (configuration.packages.length > 1) { + navList.addContent(getNavLinkPackage()); + } + navList.addContent(getNavLinkClass()); + if(configuration.classuse) { + navList.addContent(getNavLinkClassUse()); + } + if(configuration.createtree) { + navList.addContent(getNavLinkTree()); + } + if(!(configuration.nodeprecated || + configuration.nodeprecatedlist)) { + navList.addContent(getNavLinkDeprecated()); + } + if(configuration.createindex) { + navList.addContent(getNavLinkIndex()); + } + if (!configuration.nohelp) { + navList.addContent(getNavLinkHelp()); + } + navDiv.addContent(navList); + Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, getUserHeaderFooter(header)); + navDiv.addContent(aboutDiv); + body.addContent(navDiv); + Content ulNav = HtmlTree.UL(HtmlStyle.navList, getNavLinkPrevious()); + ulNav.addContent(getNavLinkNext()); + Content subDiv = HtmlTree.DIV(HtmlStyle.subNav, ulNav); + Content ulFrames = HtmlTree.UL(HtmlStyle.navList, getNavShowLists()); + ulFrames.addContent(getNavHideLists(filename)); + subDiv.addContent(ulFrames); + HtmlTree ulAllClasses = HtmlTree.UL(HtmlStyle.navList, getNavLinkClassIndex()); + ulAllClasses.addAttr(HtmlAttr.ID, allClassesId.toString()); + subDiv.addContent(ulAllClasses); + subDiv.addContent(getAllClassesLinkScript(allClassesId.toString())); + addSummaryDetailLinks(subDiv); + if (header) { + subDiv.addContent(getMarkerAnchor("skip-navbar_top")); + body.addContent(subDiv); + body.addContent(HtmlConstants.END_OF_TOP_NAVBAR); + } else { + subDiv.addContent(getMarkerAnchor("skip-navbar_bottom")); + body.addContent(subDiv); + body.addContent(HtmlConstants.END_OF_BOTTOM_NAVBAR); + } + } + } + /** * Print the word "NEXT" to indicate that no link is available. Override * this method to customize next link. @@ -525,6 +744,16 @@ public class HtmlDocletWriter extends HtmlDocWriter { navLinkNext(null); } + /** + * Get the word "NEXT" to indicate that no link is available. Override + * this method to customize next link. + * + * @return a content tree for the link + */ + protected Content getNavLinkNext() { + return getNavLinkNext(null); + } + /** * Print the word "PREV" to indicate that no link is available. Override * this method to customize prev link. @@ -533,12 +762,28 @@ public class HtmlDocletWriter extends HtmlDocWriter { navLinkPrevious(null); } + /** + * Get the word "PREV" to indicate that no link is available. Override + * this method to customize prev link. + * + * @return a content tree for the link + */ + protected Content getNavLinkPrevious() { + return getNavLinkPrevious(null); + } + /** * Do nothing. This is the default method. */ protected void printSummaryDetailLinks() { } + /** + * Do nothing. This is the default method. + */ + protected void addSummaryDetailLinks(Content navDiv) { + } + /** * Print link to the "overview-summary.html" page. */ @@ -549,6 +794,18 @@ public class HtmlDocletWriter extends HtmlDocWriter { navCellEnd(); } + /** + * Get link to the "overview-summary.html" page. + * + * @return a content tree for the link + */ + protected Content getNavLinkContents() { + Content linkContent = getHyperLink(relativePath + + "overview-summary.html", "", overviewLabel, "", ""); + Content li = HtmlTree.LI(linkContent); + return li; + } + /** * Description for a cell in the navigation bar. */ @@ -589,6 +846,19 @@ public class HtmlDocletWriter extends HtmlDocWriter { navCellEnd(); } + /** + * Get link to the "package-summary.html" page for the package passed. + * + * @param pkg Package to which link will be generated + * @return a content tree for the link + */ + protected Content getNavLinkPackage(PackageDoc pkg) { + Content linkContent = getPackageLink(pkg, + packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } + /** * Print the word "Package" in the navigation bar cell, to indicate that * link is not available here. @@ -601,6 +871,16 @@ public class HtmlDocletWriter extends HtmlDocWriter { navCellEnd(); } + /** + * Get the word "Package" , to indicate that link is not available here. + * + * @return a content tree for the link + */ + protected Content getNavLinkPackage() { + Content li = HtmlTree.LI(packageLabel); + return li; + } + /** * Print the word "Use" in the navigation bar cell, to indicate that link * is not available. @@ -613,6 +893,16 @@ public class HtmlDocletWriter extends HtmlDocWriter { navCellEnd(); } + /** + * Get the word "Use", to indicate that link is not available. + * + * @return a content tree for the link + */ + protected Content getNavLinkClassUse() { + Content li = HtmlTree.LI(useLabel); + return li; + } + /** * Print link for previous file. * @@ -627,6 +917,22 @@ public class HtmlDocletWriter extends HtmlDocWriter { } } + /** + * Get link for previous file. + * + * @param prev File name for the prev link + * @return a content tree for the link + */ + public Content getNavLinkPrevious(String prev) { + Content li; + if (prev != null) { + li = HtmlTree.LI(getHyperLink(prev, "", prevLabel, "", "")); + } + else + li = HtmlTree.LI(prevLabel); + return li; + } + /** * Print link for next file. If next is null, just print the label * without linking it anywhere. @@ -642,16 +948,46 @@ public class HtmlDocletWriter extends HtmlDocWriter { } } + /** + * Get link for next file. If next is null, just print the label + * without linking it anywhere. + * + * @param next File name for the next link + * @return a content tree for the link + */ + public Content getNavLinkNext(String next) { + Content li; + if (next != null) { + li = HtmlTree.LI(getHyperLink(next, "", nextLabel, "", "")); + } + else + li = HtmlTree.LI(nextLabel); + return li; + } + /** * Print "FRAMES" link, to switch to the frame version of the output. * * @param link File to be linked, "index.html". */ protected void navShowLists(String link) { - print(getHyperLink(link + "?" + path + filename, "", + print(getHyperLinkString(link + "?" + path + filename, "", configuration.getText("doclet.FRAMES"), true, "", "", "_top")); } + /** + * Get "FRAMES" link, to switch to the frame version of the output. + * + * @param link File to be linked, "index.html" + * @return a content tree for the link + */ + protected Content getNavShowLists(String link) { + Content framesContent = getHyperLink(link + "?" + path + + filename, "", framesLabel, "", "_top"); + Content li = HtmlTree.LI(framesContent); + return li; + } + /** * Print "FRAMES" link, to switch to the frame version of the output. */ @@ -659,16 +995,37 @@ public class HtmlDocletWriter extends HtmlDocWriter { navShowLists(relativePath + "index.html"); } + /** + * Get "FRAMES" link, to switch to the frame version of the output. + * + * @return a content tree for the link + */ + protected Content getNavShowLists() { + return getNavShowLists(relativePath + "index.html"); + } + /** * Print "NO FRAMES" link, to switch to the non-frame version of the output. * * @param link File to be linked. */ protected void navHideLists(String link) { - print(getHyperLink(link, "", configuration.getText("doclet.NO_FRAMES"), + print(getHyperLinkString(link, "", configuration.getText("doclet.NO_FRAMES"), true, "", "", "_top")); } + /** + * Get "NO FRAMES" link, to switch to the non-frame version of the output. + * + * @param link File to be linked + * @return a content tree for the link + */ + protected Content getNavHideLists(String link) { + Content noFramesContent = getHyperLink(link, "", noframesLabel, "", "_top"); + Content li = HtmlTree.LI(noFramesContent); + return li; + } + /** * Print "Tree" link in the navigation bar. If there is only one package * specified on the command line, then the "Tree" link will be to the @@ -689,10 +1046,39 @@ public class HtmlDocletWriter extends HtmlDocWriter { } /** - * Print "Tree" link to the "overview-tree.html" file. + * Get "Tree" link in the navigation bar. If there is only one package + * specified on the command line, then the "Tree" link will be to the + * only "package-tree.html" file otherwise it will be to the + * "overview-tree.html" file. + * + * @return a content tree for the link */ - protected void navLinkMainTree(String label) { - printHyperLink(relativePath + "overview-tree.html", label); + protected Content getNavLinkTree() { + Content treeLinkContent; + PackageDoc[] packages = configuration.root.specifiedPackages(); + if (packages.length == 1 && configuration.root.specifiedClasses().length == 0) { + treeLinkContent = getHyperLink(pathString(packages[0], + "package-tree.html"), "", treeLabel, + "", ""); + } else { + treeLinkContent = getHyperLink(relativePath + "overview-tree.html", + "", treeLabel, "", ""); + } + Content li = HtmlTree.LI(treeLinkContent); + return li; + } + + /** + * Get the overview tree link for the main tree. + * + * @param label the label for the link + * @return a content tree for the link + */ + protected Content getNavLinkMainTree(String label) { + Content mainTreeContent = getHyperLink(relativePath + "overview-tree.html", + new StringContent(label)); + Content li = HtmlTree.LI(mainTreeContent); + return li; } /** @@ -707,6 +1093,16 @@ public class HtmlDocletWriter extends HtmlDocWriter { navCellEnd(); } + /** + * Get the word "Class", to indicate that class link is not available. + * + * @return a content tree for the link + */ + protected Content getNavLinkClass() { + Content li = HtmlTree.LI(classLabel); + return li; + } + /** * Print "Deprecated" API link in the navigation bar. */ @@ -717,6 +1113,18 @@ public class HtmlDocletWriter extends HtmlDocWriter { navCellEnd(); } + /** + * Get "Deprecated" API link in the navigation bar. + * + * @return a content tree for the link + */ + protected Content getNavLinkDeprecated() { + Content linkContent = getHyperLink(relativePath + + "deprecated-list.html", "", deprecatedLabel, "", ""); + Content li = HtmlTree.LI(linkContent); + return li; + } + /** * Print link for generated index. If the user has used "-splitindex" * command line option, then link to file "index-files/index-1.html" is @@ -727,6 +1135,21 @@ public class HtmlDocletWriter extends HtmlDocWriter { AllClassesFrameWriter.OUTPUT_FILE_NAME_NOFRAMES, "", "", configuration.getText("doclet.All_Classes"), true); } + + /** + * Get link for generated index. If the user has used "-splitindex" + * command line option, then link to file "index-files/index-1.html" is + * generated otherwise link to file "index-all.html" is generated. + * + * @return a content tree for the link + */ + protected Content getNavLinkClassIndex() { + Content allClassesContent = getHyperLink(relativePath + + AllClassesFrameWriter.OUTPUT_FILE_NAME_NOFRAMES, "", + allclassesLabel, "", ""); + Content li = HtmlTree.LI(allClassesContent); + return li; + } /** * Print link for generated class index. */ @@ -742,6 +1165,20 @@ public class HtmlDocletWriter extends HtmlDocWriter { navCellEnd(); } + /** + * Get link for generated class index. + * + * @return a content tree for the link + */ + protected Content getNavLinkIndex() { + Content linkContent = getHyperLink(relativePath +(configuration.splitindex? + DirectoryManager.getPath("index-files") + fileseparator: "") + + (configuration.splitindex?"index-1.html" : "index-all.html"), "", + indexLabel, "", ""); + Content li = HtmlTree.LI(linkContent); + return li; + } + /** * Print help file link. If user has provided a help file, then generate a * link to the user given file, which is already copied to current or @@ -763,6 +1200,29 @@ public class HtmlDocletWriter extends HtmlDocWriter { navCellEnd(); } + /** + * Get help file link. If user has provided a help file, then generate a + * link to the user given file, which is already copied to current or + * destination directory. + * + * @return a content tree for the link + */ + protected Content getNavLinkHelp() { + String helpfilenm = configuration.helpfile; + if (helpfilenm.equals("")) { + helpfilenm = "help-doc.html"; + } else { + int lastsep; + if ((lastsep = helpfilenm.lastIndexOf(File.separatorChar)) != -1) { + helpfilenm = helpfilenm.substring(lastsep + 1); + } + } + Content linkContent = getHyperLink(relativePath + helpfilenm, "", + helpLabel, "", ""); + Content li = HtmlTree.LI(linkContent); + return li; + } + /** * Print the word "Detail" in the navigation bar. No link is available. */ @@ -844,6 +1304,96 @@ public class HtmlDocletWriter extends HtmlDocWriter { trEnd(); } + /** + * Get summary table header. + * + * @param header the header for the table + * @param scope the scope of the headers + * @return a content tree for the header + */ + public Content getSummaryTableHeader(String[] header, String scope) { + Content tr = new HtmlTree(HtmlTag.TR); + int size = header.length; + Content tableHeader; + if (size == 1) { + tableHeader = new StringContent(header[0]); + tr.addContent(HtmlTree.TH(HtmlStyle.colOne, scope, tableHeader)); + return tr; + } + for (int i = 0; i < size; i++) { + tableHeader = new StringContent(header[i]); + if(i == 0) + tr.addContent(HtmlTree.TH(HtmlStyle.colFirst, scope, tableHeader)); + else if(i == (size - 1)) + tr.addContent(HtmlTree.TH(HtmlStyle.colLast, scope, tableHeader)); + else + tr.addContent(HtmlTree.TH(scope, tableHeader)); + } + return tr; + } + + /** + * Get table caption. + * + * @param rawText the caption for the table which could be raw Html + * @return a content tree for the caption + */ + public Content getTableCaption(String rawText) { + Content title = new RawHtml(rawText); + Content captionSpan = HtmlTree.SPAN(title); + Content space = getSpace(); + Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, space); + Content caption = HtmlTree.CAPTION(captionSpan); + caption.addContent(tabSpan); + return caption; + } + + /** + * Get the marker anchor which will be added to the documentation tree. + * + * @param anchorName the anchor name attribute + * @return a content tree for the marker anchor + */ + public Content getMarkerAnchor(String anchorName) { + return getMarkerAnchor(anchorName, null); + } + + /** + * Get the marker anchor which will be added to the documentation tree. + * + * @param anchorName the anchor name attribute + * @param anchorContent the content that should be added to the anchor + * @return a content tree for the marker anchor + */ + public Content getMarkerAnchor(String anchorName, Content anchorContent) { + if (anchorContent == null) + anchorContent = new Comment(" "); + Content markerAnchor = HtmlTree.A_NAME(anchorName, anchorContent); + return markerAnchor; + } + + /** + * Returns a packagename content. + * + * @param packageDoc the package to check + * @return package name content + */ + public Content getPackageName(PackageDoc packageDoc) { + return packageDoc == null || packageDoc.name().length() == 0 ? + defaultPackageLabel : + getPackageLabel(packageDoc.name()); + } + + /** + * Returns a package name label. + * + * @param parsedName the package name + * @return the package name content + */ + public Content getPackageLabel(String packageName) { + return new StringContent(packageName); + } + /** * Prine table header information about color, column span and the font. * @@ -1028,7 +1578,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param isStrong true if the label should be strong. */ public void printPackageLink(PackageDoc pkg, String label, boolean isStrong) { - print(getPackageLink(pkg, label, isStrong)); + print(getPackageLinkString(pkg, label, isStrong)); } /** @@ -1041,7 +1591,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { */ public void printPackageLink(PackageDoc pkg, String label, boolean isStrong, String style) { - print(getPackageLink(pkg, label, isStrong, style)); + print(getPackageLinkString(pkg, label, isStrong, style)); } /** @@ -1052,9 +1602,9 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param isStrong true if the label should be strong. * @return the link to the given package. */ - public String getPackageLink(PackageDoc pkg, String label, + public String getPackageLinkString(PackageDoc pkg, String label, boolean isStrong) { - return getPackageLink(pkg, label, isStrong, ""); + return getPackageLinkString(pkg, label, isStrong, ""); } /** @@ -1066,7 +1616,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param style the font of the package link label. * @return the link to the given package. */ - public String getPackageLink(PackageDoc pkg, String label, boolean isStrong, + public String getPackageLinkString(PackageDoc pkg, String label, boolean isStrong, String style) { boolean included = pkg != null && pkg.isIncluded(); if (! included) { @@ -1079,12 +1629,43 @@ public class HtmlDocletWriter extends HtmlDocWriter { } } if (included || pkg == null) { - return getHyperLink(pathString(pkg, "package-summary.html"), + return getHyperLinkString(pathString(pkg, "package-summary.html"), "", label, isStrong, style); } else { String crossPkgLink = getCrossPackageLink(Util.getPackageName(pkg)); if (crossPkgLink != null) { - return getHyperLink(crossPkgLink, "", label, isStrong, style); + return getHyperLinkString(crossPkgLink, "", label, isStrong, style); + } else { + return label; + } + } + } + + /** + * Return the link to the given package. + * + * @param pkg the package to link to. + * @param label the label for the link. + * @return a content tree for the package link. + */ + public Content getPackageLink(PackageDoc pkg, Content label) { + boolean included = pkg != null && pkg.isIncluded(); + if (! included) { + PackageDoc[] packages = configuration.packages; + for (int i = 0; i < packages.length; i++) { + if (packages[i].equals(pkg)) { + included = true; + break; + } + } + } + if (included || pkg == null) { + return getHyperLink(pathString(pkg, "package-summary.html"), + "", label); + } else { + String crossPkgLink = getCrossPackageLink(Util.getPackageName(pkg)); + if (crossPkgLink != null) { + return getHyperLink(crossPkgLink, "", label); } else { return label; } @@ -1111,6 +1692,29 @@ public class HtmlDocletWriter extends HtmlDocWriter { printHyperLink(href, "", label, true); } + /** + * Add the link to the content tree. + * + * @param doc program element doc for which the link will be added + * @param label label for the link + * @param htmltree the content tree to which the link will be added + */ + public void addSrcLink(ProgramElementDoc doc, Content label, Content htmltree) { + if (doc == null) { + return; + } + ClassDoc cd = doc.containingClass(); + if (cd == null) { + //d must be a class doc since in has no containing class. + cd = (ClassDoc) doc; + } + String href = relativePath + DocletConstants.SOURCE_OUTPUT_DIR_NAME + + DirectoryManager.getDirectoryPath(cd.containingPackage()) + + cd.name() + ".html#" + SourceToHTMLConverter.getAnchorName(doc); + Content linkContent = getHyperLink(href, "", label, "", ""); + htmltree.addContent(linkContent); + } + /** * Return the link to the given class. * @@ -1175,7 +1779,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { //the -link option. There are ways to determine if an external package //exists, but no way to determine if the external class exists. We just //have to assume that it does. - return getHyperLink( + return getHyperLinkString( configuration.extern.getExternalLink(packageName, relativePath, className + ".html?is-external=true"), refMemName == null ? "" : refMemName, @@ -1200,17 +1804,27 @@ public class HtmlDocletWriter extends HtmlDocWriter { "package-summary.html?is-external=true"); } - public void printQualifiedClassLink(int context, ClassDoc cd) { - printLink(new LinkInfoImpl(context, cd, - configuration.getClassName(cd), "")); + /** + * Get the class link. + * + * @param context the id of the context where the link will be added + * @param cd the class doc to link to + * @return a content tree for the link + */ + public Content getQualifiedClassLink(int context, ClassDoc cd) { + return new RawHtml(getLink(new LinkInfoImpl(context, cd, + configuration.getClassName(cd), ""))); } /** - * Print Class link, with only class name as the link and prefixing - * plain package name. + * Add the class link. + * + * @param context the id of the context where the link will be added + * @param cd the class doc to link to + * @param contentTree the content tree to which the link will be added */ - public void printPreQualifiedClassLink(int context, ClassDoc cd) { - print(getPreQualifiedClassLink(context, cd, false)); + public void addPreQualifiedClassLink(int context, ClassDoc cd, Content contentTree) { + addPreQualifiedClassLink(context, cd, false, contentTree); } /** @@ -1233,13 +1847,36 @@ public class HtmlDocletWriter extends HtmlDocWriter { return classlink; } + /** + * Add the class link with the package portion of the label in + * plain text. If the qualifier is excluded, it will not be included in the + * link label. + * + * @param context the id of the context where the link will be added + * @param cd the class to link to + * @param isStrong true if the link should be strong + * @param contentTree the content tree to which the link with be added + */ + public void addPreQualifiedClassLink(int context, + ClassDoc cd, boolean isStrong, Content contentTree) { + PackageDoc pd = cd.containingPackage(); + if(pd != null && ! configuration.shouldExcludeQualifier(pd.name())) { + contentTree.addContent(getPkgName(cd)); + } + contentTree.addContent(new RawHtml(getLink(new LinkInfoImpl( + context, cd, cd.name(), isStrong)))); + } /** - * Print Class link, with only class name as the strong link and prefixing + * Add the class link, with only class name as the strong link and prefixing * plain package name. + * + * @param context the id of the context where the link will be added + * @param cd the class to link to + * @param contentTree the content tree to which the link with be added */ - public void printPreQualifiedStrongClassLink(int context, ClassDoc cd) { - print(getPreQualifiedClassLink(context, cd, true)); + public void addPreQualifiedStrongClassLink(int context, ClassDoc cd, Content contentTree) { + addPreQualifiedClassLink(context, cd, true, contentTree); } public void printText(String key) { @@ -1267,16 +1904,15 @@ public class HtmlDocletWriter extends HtmlDocWriter { } /** - * Print the link for the given member. + * Get the link for the given member. * - * @param context the id of the context where the link will be printed. - * @param doc the member being linked to. - * @param label the label for the link. - * @param strong true if the link should be strong. + * @param context the id of the context where the link will be added + * @param doc the member being linked to + * @param label the label for the link + * @return a content tree for the doc link */ - public void printDocLink(int context, MemberDoc doc, String label, - boolean strong) { - print(getDocLink(context, doc, label, strong)); + public Content getDocLink(int context, MemberDoc doc, String label) { + return getDocLink(context, doc.containingClass(), doc, label); } /** @@ -1338,6 +1974,34 @@ public class HtmlDocletWriter extends HtmlDocWriter { } } + /** + * Return the link for the given member. + * + * @param context the id of the context where the link will be added + * @param classDoc the classDoc that we should link to. This is not + * necessarily equal to doc.containingClass(). We may be + * inheriting comments + * @param doc the member being linked to + * @param label the label for the link + * @return the link for the given member + */ + public Content getDocLink(int context, ClassDoc classDoc, MemberDoc doc, + String label) { + if (! (doc.isIncluded() || + Util.isLinkable(classDoc, configuration()))) { + return new StringContent(label); + } else if (doc instanceof ExecutableMemberDoc) { + ExecutableMemberDoc emd = (ExecutableMemberDoc)doc; + return new RawHtml(getLink(new LinkInfoImpl(context, classDoc, + getAnchor(emd), label, false))); + } else if (doc instanceof MemberDoc) { + return new RawHtml(getLink(new LinkInfoImpl(context, classDoc, + doc.name(), label, false))); + } else { + return new StringContent(label); + } + } + public void anchor(ExecutableMemberDoc emd) { anchor(getAnchor(emd)); } @@ -1392,14 +2056,14 @@ public class HtmlDocletWriter extends HtmlDocWriter { //@see is referencing an included package String packageName = isplaintext ? refPackage.name() : getCode() + refPackage.name() + getCodeEnd(); - result.append(getPackageLink(refPackage, + result.append(getPackageLinkString(refPackage, label.length() == 0 ? packageName : label, false)); } else { //@see is not referencing an included class or package. Check for cross links. String classCrossLink, packageCrossLink = getCrossPackageLink(refClassName); if (packageCrossLink != null) { //Package cross link found - result.append(getHyperLink(packageCrossLink, "", + result.append(getHyperLinkString(packageCrossLink, "", (label.length() == 0)? text : label, false)); } else if ((classCrossLink = getCrossClassLink(refClassName, refMemName, label, false, "", ! isplaintext)) != null) { @@ -1468,18 +2132,61 @@ public class HtmlDocletWriter extends HtmlDocWriter { printCommentTags(doc, tag.inlineTags(), false, false); } + /** + * Add the inline comment. + * + * @param doc the doc for which the inline comment will be added + * @param tag the inline tag to be added + * @param htmltree the content tree to which the comment will be added + */ + public void addInlineComment(Doc doc, Tag tag, Content htmltree) { + addCommentTags(doc, tag.inlineTags(), false, false, htmltree); + } + public void printInlineDeprecatedComment(Doc doc, Tag tag) { printCommentTags(doc, tag.inlineTags(), true, false); } + /** + * Add the inline deprecated comment. + * + * @param doc the doc for which the inline deprecated comment will be added + * @param tag the inline tag to be added + * @param htmltree the content tree to which the comment will be added + */ + public void addInlineDeprecatedComment(Doc doc, Tag tag, Content htmltree) { + addCommentTags(doc, tag.inlineTags(), true, false, htmltree); + } + public void printSummaryComment(Doc doc) { printSummaryComment(doc, doc.firstSentenceTags()); } + /** + * Adds the summary content. + * + * @param doc the doc for which the summary will be generated + * @param htmltree the documentation tree to which the summary will be added + */ + public void addSummaryComment(Doc doc, Content htmltree) { + addSummaryComment(doc, doc.firstSentenceTags(), htmltree); + } + public void printSummaryComment(Doc doc, Tag[] firstSentenceTags) { printCommentTags(doc, firstSentenceTags, false, true); } + /** + * Adds the summary content. + * + * @param doc the doc for which the summary will be generated + * @param firstSentenceTags the first sentence tags for the doc + * @param htmltree the documentation tree to which the summary will be added + */ + public void addSummaryComment(Doc doc, Tag[] firstSentenceTags, Content htmltree) { + addCommentTags(doc, firstSentenceTags, false, true, htmltree); + } + public void printSummaryDeprecatedComment(Doc doc) { printCommentTags(doc, doc.firstSentenceTags(), true, true); } @@ -1488,11 +2195,25 @@ public class HtmlDocletWriter extends HtmlDocWriter { printCommentTags(doc, tag.firstSentenceTags(), true, true); } + public void addSummaryDeprecatedComment(Doc doc, Tag tag, Content htmltree) { + addCommentTags(doc, tag.firstSentenceTags(), true, true, htmltree); + } + public void printInlineComment(Doc doc) { printCommentTags(doc, doc.inlineTags(), false, false); p(); } + /** + * Adds the inline comment. + * + * @param doc the doc for which the inline comments will be generated + * @param htmltree the documentation tree to which the inline comments will be added + */ + public void addInlineComment(Doc doc, Content htmltree) { + addCommentTags(doc, doc.inlineTags(), false, false, htmltree); + } + public void printInlineDeprecatedComment(Doc doc) { printCommentTags(doc, doc.inlineTags(), true, false); } @@ -1514,6 +2235,36 @@ public class HtmlDocletWriter extends HtmlDocWriter { } } + /** + * Adds the comment tags. + * + * @param doc the doc for which the comment tags will be generated + * @param tags the first sentence tags for the doc + * @param depr true if it is deprecated + * @param first true if the first sentenge tags should be added + * @param htmltree the documentation tree to which the comment tags will be added + */ + private void addCommentTags(Doc doc, Tag[] tags, boolean depr, + boolean first, Content htmltree) { + if(configuration.nocomment){ + return; + } + Content div; + Content result = new RawHtml(commentTagsToString(null, doc, tags, first)); + if (depr) { + Content italic = HtmlTree.I(result); + div = HtmlTree.DIV(HtmlStyle.block, italic); + htmltree.addContent(div); + } + else { + div = HtmlTree.DIV(HtmlStyle.block, result); + htmltree.addContent(div); + } + if (tags.length == 0) { + htmltree.addContent(getSpace()); + } + } + /** * Converts inline tags and text to text strings, expanding the * inline tags along the way. Called wherever text can contain @@ -1624,8 +2375,8 @@ public class HtmlDocletWriter extends HtmlDocWriter { return text; } - if (! redirectPathFromRoot.endsWith(DirectoryManager.URL_FILE_SEPERATOR)) { - redirectPathFromRoot += DirectoryManager.URL_FILE_SEPERATOR; + if (! redirectPathFromRoot.endsWith(DirectoryManager.URL_FILE_SEPARATOR)) { + redirectPathFromRoot += DirectoryManager.URL_FILE_SEPARATOR; } //Redirect all relative links. @@ -1750,6 +2501,27 @@ public class HtmlDocletWriter extends HtmlDocWriter { filename + "\" " + "TITLE=\"Style\""); } + /** + * Returns a link to the stylesheet file. + * + * @return an HtmlTree for the lINK tag which provides the stylesheet location + */ + public HtmlTree getStyleSheetProperties() { + String filename = configuration.stylesheetfile; + if (filename.length() > 0) { + File stylefile = new File(filename); + String parent = stylefile.getParent(); + filename = (parent == null)? + filename: + filename.substring(parent.length() + 1); + } else { + filename = "stylesheet.css"; + } + filename = relativePath + filename; + HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", filename, "Style"); + return link; + } + /** * According to the Java Language Specifications, all the outer classes * and static nested classes are core classes. @@ -1767,6 +2539,17 @@ public class HtmlDocletWriter extends HtmlDocWriter { writeAnnotationInfo(packageDoc, packageDoc.annotations()); } + /** + * Adds the annotatation types for the given packageDoc. + * + * @param packageDoc the package to write annotations for. + * @param htmltree the documentation tree to which the annotation info will be + * added + */ + public void addAnnotationInfo(PackageDoc packageDoc, Content htmltree) { + addAnnotationInfo(packageDoc, packageDoc.annotations(), htmltree); + } + /** * Write the annotatation types for the given doc. * @@ -1776,6 +2559,16 @@ public class HtmlDocletWriter extends HtmlDocWriter { writeAnnotationInfo(doc, doc.annotations()); } + /** + * Adds the annotatation types for the given doc. + * + * @param packageDoc the package to write annotations for + * @param htmltree the content tree to which the annotation types will be added + */ + public void addAnnotationInfo(ProgramElementDoc doc, Content htmltree) { + addAnnotationInfo(doc, doc.annotations(), htmltree); + } + /** * Write the annotatation types for the given doc and parameter. * @@ -1787,6 +2580,19 @@ public class HtmlDocletWriter extends HtmlDocWriter { return writeAnnotationInfo(indent, doc, param.annotations(), false); } + /** + * Add the annotatation types for the given doc and parameter. + * + * @param indent the number of spaces to indent the parameters. + * @param doc the doc to write annotations for. + * @param param the parameter to write annotations for. + * @param tree the content tree to which the annotation types will be added + */ + public boolean addAnnotationInfo(int indent, Doc doc, Parameter param, + Content tree) { + return addAnnotationInfo(indent, doc, param.annotations(), false, tree); + } + /** * Write the annotatation types for the given doc. * @@ -1797,6 +2603,19 @@ public class HtmlDocletWriter extends HtmlDocWriter { writeAnnotationInfo(0, doc, descList, true); } + /** + * Adds the annotatation types for the given doc. + * + * @param doc the doc to write annotations for. + * @param descList the array of {@link AnnotationDesc}. + * @param htmltree the documentation tree to which the annotation info will be + * added + */ + private void addAnnotationInfo(Doc doc, AnnotationDesc[] descList, + Content htmltree) { + addAnnotationInfo(0, doc, descList, true, htmltree); + } + /** * Write the annotatation types for the given doc. * @@ -1818,6 +2637,29 @@ public class HtmlDocletWriter extends HtmlDocWriter { } /** + * Adds the annotatation types for the given doc. + * + * @param indent the number of extra spaces to indent the annotations. + * @param doc the doc to write annotations for. + * @param descList the array of {@link AnnotationDesc}. + * @param htmltree the documentation tree to which the annotation info will be + * added + */ + private boolean addAnnotationInfo(int indent, Doc doc, + AnnotationDesc[] descList, boolean lineBreak, Content htmltree) { + List annotations = getAnnotations(indent, descList, lineBreak); + if (annotations.size() == 0) { + return false; + } + Content annotationContent; + for (Iterator iter = annotations.iterator(); iter.hasNext();) { + annotationContent = new RawHtml(iter.next()); + htmltree.addContent(annotationContent); + } + return true; + } + + /** * Return the string representations of the annotation types for * the given doc. * diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java index cb438b7c748..9570c7ca39e 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java @@ -31,6 +31,7 @@ import com.sun.javadoc.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.taglets.*; import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Generate serialized form for serializable fields. @@ -46,8 +47,6 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl private boolean printedOverallAnchor = false; - private boolean printedFirstMember = false; - public HtmlSerialFieldWriter(SubWriterHolderWriter writer, ClassDoc classdoc) { super(writer, classdoc); @@ -69,109 +68,143 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl } } - public void writeHeader(String heading) { - if (! printedOverallAnchor) { - writer.anchor("serializedForm"); - printedOverallAnchor = true; - writer.printTableHeadingBackground(heading); - writer.println(); - if (heading.equals( - configuration().getText("doclet.Serialized_Form_class"))) { - assert !writer.getMemberDetailsListPrinted(); + /** + * Return the header for serializable fields section. + * + * @return a content tree for the header + */ + public Content getSerializableFieldsHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * Return the header for serializable fields content section. + * + * @param isLastContent true if the cotent being documented is the last content. + * @return a content tree for the header + */ + public Content getFieldsContentHeader(boolean isLastContent) { + HtmlTree li = new HtmlTree(HtmlTag.LI); + if (isLastContent) + li.addStyle(HtmlStyle.blockListLast); + else + li.addStyle(HtmlStyle.blockList); + return li; + } + + /** + * Add serializable fields. + * + * @param heading the heading for the section + * @param serializableFieldsTree the tree to be added to the serializable fileds + * content tree + * @return a content tree for the serializable fields content + */ + public Content getSerializableFields(String heading, Content serializableFieldsTree) { + HtmlTree li = new HtmlTree(HtmlTag.LI); + li.addStyle(HtmlStyle.blockList); + if (serializableFieldsTree.isValid()) { + if (!printedOverallAnchor) { + li.addContent(writer.getMarkerAnchor("serializedForm")); + printedOverallAnchor = true; } - } else { - writer.printTableHeadingBackground(heading); - writer.println(); + Content headingContent = new StringContent(heading); + Content serialHeading = HtmlTree.HEADING(HtmlConstants.SERIALIZED_MEMBER_HEADING, + headingContent); + li.addContent(serialHeading); + li.addContent(serializableFieldsTree); } + return li; } - public void writeMemberHeader(ClassDoc fieldType, String fieldTypeStr, - String fieldDimensions, String fieldName) { - if (printedFirstMember) { - writer.printMemberHeader(); - } - printedFirstMember = true; - writer.h3(); - writer.print(fieldName); - writer.h3End(); - writer.pre(); + /** + * Add the member header. + * + * @param fieldsType the class document to be listed + * @param fieldTypeStr the string for the filed type to be documented + * @param fieldDimensions the dimensions of the field string to be added + * @param firldName name of the field to be added + * @param contentTree the content tree to which the member header will be added + */ + public void addMemberHeader(ClassDoc fieldType, String fieldTypeStr, + String fieldDimensions, String fieldName, Content contentTree) { + Content nameContent = new RawHtml(fieldName); + Content heading = HtmlTree.HEADING(HtmlConstants.MEMBER_HEADING, nameContent); + contentTree.addContent(heading); + Content pre = new HtmlTree(HtmlTag.PRE); if (fieldType == null) { - writer.print(fieldTypeStr); + pre.addContent(fieldTypeStr); } else { - writer.printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_SERIAL_MEMBER, - fieldType)); + Content fieldContent = new RawHtml(writer.getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_SERIAL_MEMBER, fieldType))); + pre.addContent(fieldContent); } - print(fieldDimensions + ' '); - strong(fieldName); - writer.preEnd(); - assert !writer.getMemberDetailsListPrinted(); + pre.addContent(fieldDimensions + " "); + pre.addContent(fieldName); + contentTree.addContent(pre); } /** - * Write the deprecated information for this member. + * Add the deprecated information for this member. * * @param field the field to document. + * @param contentTree the tree to which the deprecated info will be added */ - public void writeMemberDeprecatedInfo(FieldDoc field) { - printDeprecated(field); + public void addMemberDeprecatedInfo(FieldDoc field, Content contentTree) { + addDeprecatedInfo(field, contentTree); } /** - * Write the description text for this member. + * Add the description text for this member. * * @param field the field to document. + * @param contentTree the tree to which the deprecated info will be added */ - public void writeMemberDescription(FieldDoc field) { + public void addMemberDescription(FieldDoc field, Content contentTree) { if (field.inlineTags().length > 0) { - writer.printMemberDetailsListStartTag(); - writer.dd(); - writer.printInlineComment(field); - writer.ddEnd(); + writer.addInlineComment(field, contentTree); } Tag[] tags = field.tags("serial"); if (tags.length > 0) { - writer.printMemberDetailsListStartTag(); - writer.dd(); - writer.printInlineComment(field, tags[0]); - writer.ddEnd(); + writer.addInlineComment(field, tags[0], contentTree); } } /** - * Write the description text for this member represented by the tag. + * Add the description text for this member represented by the tag. * - * @param serialFieldTag the field to document (represented by tag). + * @param serialFieldTag the field to document (represented by tag) + * @param contentTree the tree to which the deprecated info will be added */ - public void writeMemberDescription(SerialFieldTag serialFieldTag) { + public void addMemberDescription(SerialFieldTag serialFieldTag, Content contentTree) { String serialFieldTagDesc = serialFieldTag.description().trim(); if (!serialFieldTagDesc.isEmpty()) { - writer.dl(); - writer.dd(); - writer.print(serialFieldTagDesc); - writer.ddEnd(); - writer.dlEnd(); + Content serialFieldContent = new RawHtml(serialFieldTagDesc); + Content div = HtmlTree.DIV(HtmlStyle.block, serialFieldContent); + contentTree.addContent(div); } } /** - * Write the tag information for this member. + * Add the tag information for this member. * * @param field the field to document. + * @param contentTree the tree to which the member tags info will be added */ - public void writeMemberTags(FieldDoc field) { + public void addMemberTags(FieldDoc field, Content contentTree) { TagletOutputImpl output = new TagletOutputImpl(""); TagletWriter.genTagOuput(configuration().tagletManager, field, - configuration().tagletManager.getCustomTags(field), + configuration().tagletManager.getCustomTags(field), writer.getTagletWriterInstance(false), output); String outputString = output.toString().trim(); + Content dlTags = new HtmlTree(HtmlTag.DL); if (!outputString.isEmpty()) { - writer.printMemberDetailsListStartTag(); - writer.dd(); - writer.dl(); - print(outputString); - writer.dlEnd(); - writer.ddEnd(); + Content tagContent = new RawHtml(outputString); + dlTags.addContent(tagContent); } + contentTree.addContent(dlTags); } /** @@ -192,24 +225,4 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl return true; return false; } - - public void writeMemberFooter() { - printMemberFooter(); - } - - /** - * Write the footer information. If the serilization overview section was - * printed, check for definition list and close list tag. - * - * @param heading the heading that was written. - */ - public void writeFooter(String heading) { - if (printedOverallAnchor) { - if (heading.equals( - configuration().getText("doclet.Serialized_Form_class"))) { - writer.printMemberDetailsListEndTag(); - assert !writer.getMemberDetailsListPrinted(); - } - } - } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialMethodWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialMethodWriter.java index fdce605169e..18bb936e0aa 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialMethodWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialMethodWriter.java @@ -28,57 +28,119 @@ package com.sun.tools.doclets.formats.html; import com.sun.javadoc.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.taglets.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Generate serialized form for Serializable/Externalizable methods. * Documentation denoted by the serialData tag is processed. * * @author Joe Fialli + * @author Bhavesh Patel (Modified) */ public class HtmlSerialMethodWriter extends MethodWriterImpl implements SerializedFormWriter.SerialMethodWriter{ - private boolean printedFirstMember = false; - public HtmlSerialMethodWriter(SubWriterHolderWriter writer, ClassDoc classdoc) { super(writer, classdoc); } - public void writeHeader(String heading) { - writer.anchor("serialized_methods"); - writer.printTableHeadingBackground(heading); - writer.p(); + /** + * Return the header for serializable methods section. + * + * @return a content tree for the header + */ + public Content getSerializableMethodsHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; } - public void writeNoCustomizationMsg(String msg) { - writer.print(msg); - writer.p(); + /** + * Return the header for serializable methods content section. + * + * @param isLastContent true if the cotent being documented is the last content. + * @return a content tree for the header + */ + public Content getMethodsContentHeader(boolean isLastContent) { + HtmlTree li = new HtmlTree(HtmlTag.LI); + if (isLastContent) + li.addStyle(HtmlStyle.blockListLast); + else + li.addStyle(HtmlStyle.blockList); + return li; } - public void writeMemberHeader(MethodDoc member) { - if (printedFirstMember) { - writer.printMemberHeader(); - } - printedFirstMember = true; - writer.anchor(member); - printHead(member); - writeSignature(member); + /** + * Add serializable methods. + * + * @param heading the heading for the section + * @param serializableMethodContent the tree to be added to the serializable methods + * content tree + * @return a content tree for the serializable methods content + */ + public Content getSerializableMethods(String heading, Content serializableMethodContent) { + Content li = HtmlTree.LI(HtmlStyle.blockList, writer.getMarkerAnchor( + "serialized_methods")); + Content headingContent = new StringContent(heading); + Content serialHeading = HtmlTree.HEADING(HtmlConstants.SERIALIZED_MEMBER_HEADING, + headingContent); + li.addContent(serialHeading); + li.addContent(serializableMethodContent); + return li; } - public void writeMemberFooter() { - printMemberFooter(); + /** + * Return the no customization message. + * + * @param msg the message to be displayed + * @return no customization message content + */ + public Content getNoCustomizationMsg(String msg) { + Content noCustomizationMsg = new StringContent(msg); + return noCustomizationMsg; } - public void writeDeprecatedMemberInfo(MethodDoc member) { - printDeprecated(member); + /** + * Add the member header. + * + * @param member the method document to be listed + * @param methodsContentTree the content tree to which the member header will be added + */ + public void addMemberHeader(MethodDoc member, Content methodsContentTree) { + methodsContentTree.addContent(writer.getMarkerAnchor( + writer.getAnchor(member))); + methodsContentTree.addContent(getHead(member)); + methodsContentTree.addContent(getSignature(member)); } - public void writeMemberDescription(MethodDoc member) { - printComment(member); + /** + * Add the deprecated information for this member. + * + * @param member the method to document. + * @param methodsContentTree the tree to which the deprecated info will be added + */ + public void addDeprecatedMemberInfo(MethodDoc member, Content methodsContentTree) { + addDeprecatedInfo(member, methodsContentTree); } - public void writeMemberTags(MethodDoc member) { + /** + * Add the description text for this member. + * + * @param member the method to document. + * @param methodsContentTree the tree to which the deprecated info will be added + */ + public void addMemberDescription(MethodDoc member, Content methodsContentTree) { + addComment(member, methodsContentTree); + } + + /** + * Add the tag information for this member. + * + * @param member the method to document. + * @param methodsContentTree the tree to which the member tags info will be added + */ + public void addMemberTags(MethodDoc member, Content methodsContentTree) { TagletOutputImpl output = new TagletOutputImpl(""); TagletManager tagletManager = ConfigurationImpl.getInstance().tagletManager; @@ -86,14 +148,12 @@ public class HtmlSerialMethodWriter extends MethodWriterImpl implements tagletManager.getSerializedFormTags(), writer.getTagletWriterInstance(false), output); String outputString = output.toString().trim(); + Content dlTags = new HtmlTree(HtmlTag.DL); if (!outputString.isEmpty()) { - writer.printMemberDetailsListStartTag(); - writer.dd(); - writer.dl(); - print(outputString); - writer.dlEnd(); - writer.ddEnd(); + Content tagContent = new RawHtml(outputString); + dlTags.addContent(tagContent); } + methodsContentTree.addContent(dlTags); MethodDoc method = member; if (method.name().compareTo("writeExternal") == 0 && method.tags("serialData").length == 0) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/LinkFactoryImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/LinkFactoryImpl.java index 08dc1efab27..5660889edad 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/LinkFactoryImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/LinkFactoryImpl.java @@ -79,7 +79,7 @@ public class LinkFactoryImpl extends LinkFactory { String filename = pathString(classLinkInfo); if (linkInfo.linkToSelf || !(linkInfo.classDoc.name() + ".html").equals(m_writer.filename)) { - linkOutput.append(m_writer.getHyperLink(filename, + linkOutput.append(m_writer.getHyperLinkString(filename, classLinkInfo.where, label.toString(), classLinkInfo.isStrong, classLinkInfo.styleName, title, classLinkInfo.target)); diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java index 1605d807cfe..c9518d2bd38 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java @@ -28,9 +28,9 @@ package com.sun.tools.doclets.formats.html; import java.io.*; import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; -import com.sun.tools.doclets.internal.toolkit.taglets.*; /** * Writes method documentation in HTML format. @@ -43,8 +43,6 @@ import com.sun.tools.doclets.internal.toolkit.taglets.*; public class MethodWriterImpl extends AbstractExecutableMemberWriter implements MethodWriter, MemberSummaryWriter { - private boolean printedSummaryHeader = false; - /** * Construct a new MethodWriterImpl. * @@ -65,184 +63,127 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter } /** - * Write the methods summary header for the given class. - * - * @param classDoc the class the summary belongs to. + * {@inheritDoc} */ - public void writeMemberSummaryHeader(ClassDoc classDoc) { - printedSummaryHeader = true; - writer.println(); - writer.println(""); - writer.println(); - writer.printSummaryHeader(this, classDoc); - } - - /** - * Write the methods summary footer for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeMemberSummaryFooter(ClassDoc classDoc) { - writer.printSummaryFooter(this, classDoc); - } - - /** - * Write the inherited methods summary header for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeInheritedMemberSummaryHeader(ClassDoc classDoc) { - if(! printedSummaryHeader){ - //We don't want inherited summary to not be under heading. - writeMemberSummaryHeader(classDoc); - writeMemberSummaryFooter(classDoc); - printedSummaryHeader = true; - } - writer.printInheritedSummaryHeader(this, classDoc); + public Content getMemberSummaryHeader(ClassDoc classDoc, + Content memberSummaryTree) { + memberSummaryTree.addContent(HtmlConstants.START_OF_METHOD_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, classDoc, memberTree); + return memberTree; } /** * {@inheritDoc} */ - public void writeInheritedMemberSummary(ClassDoc classDoc, - ProgramElementDoc method, boolean isFirst, boolean isLast) { - writer.printInheritedSummaryMember(this, classDoc, method, isFirst); + public Content getMethodDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree) { + memberDetailsTree.addContent(HtmlConstants.START_OF_METHOD_DETAILS); + Content methodDetailsTree = writer.getMemberTreeHeader(); + methodDetailsTree.addContent(writer.getMarkerAnchor("method_detail")); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.methodDetailsLabel); + methodDetailsTree.addContent(heading); + return methodDetailsTree; } /** - * Write the inherited methods summary footer for the given class. - * - * @param classDoc the class the summary belongs to. + * {@inheritDoc} */ - public void writeInheritedMemberSummaryFooter(ClassDoc classDoc) { - writer.printInheritedSummaryFooter(this, classDoc); ; - } - - /** - * Write the header for the method documentation. - * - * @param classDoc the class that the methods belong to. - */ - public void writeHeader(ClassDoc classDoc, String header) { - writer.println(); - writer.println(""); - writer.println(); - writer.anchor("method_detail"); - writer.printTableHeadingBackground(header); - } - - /** - * Write the method header for the given method. - * - * @param method the method being documented. - * @param isFirst the flag to indicate whether or not the method is the - * first to be documented. - */ - public void writeMethodHeader(MethodDoc method, boolean isFirst) { - if (! isFirst) { - writer.printMemberHeader(); - } - writer.println(); + public Content getMethodDocTreeHeader(MethodDoc method, + Content methodDetailsTree) { String erasureAnchor; if ((erasureAnchor = getErasureAnchor(method)) != null) { - writer.anchor(erasureAnchor); + methodDetailsTree.addContent(writer.getMarkerAnchor((erasureAnchor))); } - writer.anchor(method); - writer.h3(); - writer.print(method.name()); - writer.h3End(); + methodDetailsTree.addContent( + writer.getMarkerAnchor(writer.getAnchor(method))); + Content methodDocTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(method.name()); + methodDocTree.addContent(heading); + return methodDocTree; } /** - * Write the signature for the given method. + * Get the signature for the given method. * * @param method the method being documented. + * @return a content object for the signature */ - public void writeSignature(MethodDoc method) { + public Content getSignature(MethodDoc method) { writer.displayLength = 0; - writer.pre(); - writer.writeAnnotationInfo(method); - printModifiers(method); - writeTypeParameters(method); - printReturnType(method); + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(method, pre); + addModifiers(method, pre); + addTypeParameters(method, pre); + addReturnType(method, pre); if (configuration().linksource) { - writer.printSrcLink(method, method.name()); + Content methodName = new StringContent(method.name()); + writer.addSrcLink(method, methodName, pre); } else { - strong(method.name()); + addName(method.name(), pre); } - writeParameters(method); - writeExceptions(method); - writer.preEnd(); - assert !writer.getMemberDetailsListPrinted(); + addParameters(method, pre); + addExceptions(method, pre); + return pre; } /** - * Write the deprecated output for the given method. - * - * @param method the method being documented. + * {@inheritDoc} */ - public void writeDeprecated(MethodDoc method) { - printDeprecated(method); + public void addDeprecated(MethodDoc method, Content methodDocTree) { + addDeprecatedInfo(method, methodDocTree); } /** - * Write the comments for the given method. - * - * @param method the method being documented. + * {@inheritDoc} */ - public void writeComments(Type holder, MethodDoc method) { + public void addComments(Type holder, MethodDoc method, Content methodDocTree) { ClassDoc holderClassDoc = holder.asClassDoc(); if (method.inlineTags().length > 0) { - writer.printMemberDetailsListStartTag(); if (holder.asClassDoc().equals(classdoc) || - (! (holderClassDoc.isPublic() || + (! (holderClassDoc.isPublic() || Util.isLinkable(holderClassDoc, configuration())))) { - writer.dd(); - writer.printInlineComment(method); - writer.ddEnd(); + writer.addInlineComment(method, methodDocTree); } else { - String classlink = writer.codeText( - writer.getDocLink(LinkInfoImpl.CONTEXT_METHOD_DOC_COPY, + Content link = new RawHtml( + writer.getDocLink(LinkInfoImpl.CONTEXT_METHOD_DOC_COPY, holder.asClassDoc(), method, holder.asClassDoc().isIncluded() ? holder.typeName() : holder.qualifiedTypeName(), - false)); - writer.dd(); - writer.strongText(holder.asClassDoc().isClass()? - "doclet.Description_From_Class": - "doclet.Description_From_Interface", - classlink); - writer.ddEnd(); - writer.dd(); - writer.printInlineComment(method); - writer.ddEnd(); + false)); + Content codelLink = HtmlTree.CODE(link); + Content strong = HtmlTree.STRONG(holder.asClassDoc().isClass()? + writer.descfrmClassLabel : writer.descfrmInterfaceLabel); + strong.addContent(writer.getSpace()); + strong.addContent(codelLink); + methodDocTree.addContent(HtmlTree.DIV(HtmlStyle.block, strong)); + writer.addInlineComment(method, methodDocTree); } } } /** - * Write the tag output for the given method. - * - * @param method the method being documented. + * {@inheritDoc} */ - public void writeTags(MethodDoc method) { - writer.printTags(method); + public void addTags(MethodDoc method, Content methodDocTree) { + writer.addTagsInfo(method, methodDocTree); } /** - * Write the method footer. + * {@inheritDoc} */ - public void writeMethodFooter() { - printMemberFooter(); + public Content getMethodDetails(Content methodDetailsTree) { + return getMemberTree(methodDetailsTree); } /** - * Write the footer for the method documentation. - * - * @param classDoc the class that the methods belong to. + * {@inheritDoc} */ - public void writeFooter(ClassDoc classDoc) { - //No footer to write for method documentation + public Content getMethodDoc(Content methodDocTree, + boolean isLastContent) { + return getMemberTree(methodDocTree, isLastContent); } /** @@ -256,53 +197,89 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter return VisibleMemberMap.METHODS; } - public void printSummaryLabel() { - writer.printText("doclet.Method_Summary"); + /** + * {@inheritDoc} + */ + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Method_Summary")); + memberTree.addContent(label); } - public void printTableSummary() { - writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + /** + * {@inheritDoc} + */ + public String getTableSummary() { + return configuration().getText("doclet.Member_Table_Summary", configuration().getText("doclet.Method_Summary"), - configuration().getText("doclet.methods"))); + configuration().getText("doclet.methods")); } - public void printSummaryTableHeader(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + public String getCaption() { + return configuration().getText("doclet.Methods"); + } + + /** + * {@inheritDoc} + */ + public String[] getSummaryTableHeader(ProgramElementDoc member) { String[] header = new String[] { writer.getModifierTypeHeader(), configuration().getText("doclet.0_and_1", configuration().getText("doclet.Method"), configuration().getText("doclet.Description")) }; - writer.summaryTableHeader(header, "col"); + return header; } - public void printSummaryAnchor(ClassDoc cd) { - writer.anchor("method_summary"); + /** + * {@inheritDoc} + */ + public void addSummaryAnchor(ClassDoc cd, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor("method_summary")); } - public void printInheritedSummaryAnchor(ClassDoc cd) { - writer.anchor("methods_inherited_from_class_" + - ConfigurationImpl.getInstance().getClassName(cd)); + /** + * {@inheritDoc} + */ + public void addInheritedSummaryAnchor(ClassDoc cd, Content inheritedTree) { + inheritedTree.addContent(writer.getMarkerAnchor( + "methods_inherited_from_class_" + + configuration().getClassName(cd))); } - public void printInheritedSummaryLabel(ClassDoc cd) { - String classlink = writer.getPreQualifiedClassLink( - LinkInfoImpl.CONTEXT_MEMBER, cd, false); - writer.strong(); - String key = cd.isClass()? - "doclet.Methods_Inherited_From_Class" : - "doclet.Methods_Inherited_From_Interface"; - writer.printText(key, classlink); - writer.strongEnd(); + /** + * {@inheritDoc} + */ + public void addInheritedSummaryLabel(ClassDoc cd, Content inheritedTree) { + Content classLink = new RawHtml(writer.getPreQualifiedClassLink( + LinkInfoImpl.CONTEXT_MEMBER, cd, false)); + Content label = new StringContent(cd.isClass() ? + configuration().getText("doclet.Methods_Inherited_From_Class") : + configuration().getText("doclet.Methods_Inherited_From_Interface")); + Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING, + label); + labelHeading.addContent(writer.getSpace()); + labelHeading.addContent(classLink); + inheritedTree.addContent(labelHeading); } - protected void printSummaryType(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + protected void addSummaryType(ProgramElementDoc member, Content tdSummaryType) { MethodDoc meth = (MethodDoc)member; - printModifierAndType(meth, meth.returnType()); + addModifierAndType(meth, meth.returnType(), tdSummaryType); } - protected static void printOverridden(HtmlDocletWriter writer, - Type overriddenType, MethodDoc method) { + /** + * {@inheritDoc} + */ + protected static void addOverridden(HtmlDocletWriter writer, + Type overriddenType, MethodDoc method, Content dl) { if(writer.configuration.nocomment){ return; } @@ -317,31 +294,33 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter //is not visible so don't document this. return; } - String label = "doclet.Overrides"; + Content label = writer.overridesLabel; int context = LinkInfoImpl.CONTEXT_METHOD_OVERRIDES; if (method != null) { if(overriddenType.asClassDoc().isAbstract() && method.isAbstract()){ //Abstract method is implemented from abstract class, //not overridden - label = "doclet.Specified_By"; + label = writer.specifiedByLabel; context = LinkInfoImpl.CONTEXT_METHOD_SPECIFIED_BY; } - String overriddenTypeLink = writer.codeText( - writer.getLink(new LinkInfoImpl(context, overriddenType))); + Content dt = HtmlTree.DT(HtmlTree.STRONG(label)); + dl.addContent(dt); + Content overriddenTypeLink = new RawHtml( + writer.getLink(new LinkInfoImpl(context, overriddenType))); + Content codeOverridenTypeLink = HtmlTree.CODE(overriddenTypeLink); String name = method.name(); - writer.dt(); - writer.strongText(label); - writer.dtEnd(); - writer.dd(); - String methLink = writer.codeText( - writer.getLink( + Content methlink = new RawHtml(writer.getLink( new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, - overriddenType.asClassDoc(), - writer.getAnchor(method), name, false) - )); - writer.printText("doclet.in_class", methLink, overriddenTypeLink); - writer.ddEnd(); + overriddenType.asClassDoc(), + writer.getAnchor(method), name, false))); + Content codeMethLink = HtmlTree.CODE(methlink); + Content dd = HtmlTree.DD(codeMethLink); + dd.addContent(writer.getSpace()); + dd.addContent(writer.getResource("doclet.in_class")); + dd.addContent(writer.getSpace()); + dd.addContent(codeOverridenTypeLink); + dl.addContent(dd); } } @@ -363,61 +342,78 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter } } - protected static void printImplementsInfo(HtmlDocletWriter writer, - MethodDoc method) { + /** + * {@inheritDoc} + */ + protected static void addImplementsInfo(HtmlDocletWriter writer, + MethodDoc method, Content dl) { if(writer.configuration.nocomment){ return; } ImplementedMethods implementedMethodsFinder = - new ImplementedMethods(method, writer.configuration); + new ImplementedMethods(method, writer.configuration); MethodDoc[] implementedMethods = implementedMethodsFinder.build(); for (int i = 0; i < implementedMethods.length; i++) { MethodDoc implementedMeth = implementedMethods[i]; Type intfac = implementedMethodsFinder.getMethodHolder(implementedMeth); - String methlink = ""; - String intfaclink = writer.codeText( - writer.getLink(new LinkInfoImpl( + Content intfaclink = new RawHtml(writer.getLink(new LinkInfoImpl( LinkInfoImpl.CONTEXT_METHOD_SPECIFIED_BY, intfac))); - writer.dt(); - writer.strongText("doclet.Specified_By"); - writer.dtEnd(); - writer.dd(); - methlink = writer.codeText(writer.getDocLink( - LinkInfoImpl.CONTEXT_MEMBER, implementedMeth, - implementedMeth.name(), false)); - writer.printText("doclet.in_interface", methlink, intfaclink); - writer.ddEnd(); + Content codeIntfacLink = HtmlTree.CODE(intfaclink); + Content dt = HtmlTree.DT(HtmlTree.STRONG(writer.specifiedByLabel)); + dl.addContent(dt); + Content methlink = new RawHtml(writer.getDocLink( + LinkInfoImpl.CONTEXT_MEMBER, implementedMeth, + implementedMeth.name(), false)); + Content codeMethLink = HtmlTree.CODE(methlink); + Content dd = HtmlTree.DD(codeMethLink); + dd.addContent(writer.getSpace()); + dd.addContent(writer.getResource("doclet.in_interface")); + dd.addContent(writer.getSpace()); + dd.addContent(codeIntfacLink); + dl.addContent(dd); } - } - protected void printReturnType(MethodDoc method) { + /** + * Add the return type. + * + * @param method the method being documented. + * @param htmltree the content tree to which the return type will be added + */ + protected void addReturnType(MethodDoc method, Content htmltree) { Type type = method.returnType(); if (type != null) { - writer.printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_RETURN_TYPE, - type)); - print(' '); + Content linkContent = new RawHtml(writer.getLink( + new LinkInfoImpl(LinkInfoImpl.CONTEXT_RETURN_TYPE, type))); + htmltree.addContent(linkContent); + htmltree.addContent(writer.getSpace()); } } - protected void printNavSummaryLink(ClassDoc cd, boolean link) { + /** + * {@inheritDoc} + */ + protected Content getNavSummaryLink(ClassDoc cd, boolean link) { if (link) { - writer.printHyperLink("", (cd == null)? + return writer.getHyperLink("", (cd == null)? "method_summary": "methods_inherited_from_class_" + - ConfigurationImpl.getInstance().getClassName(cd), - ConfigurationImpl.getInstance().getText("doclet.navMethod")); + configuration().getClassName(cd), + writer.getResource("doclet.navMethod")); } else { - writer.printText("doclet.navMethod"); + return writer.getResource("doclet.navMethod"); } } - protected void printNavDetailLink(boolean link) { + /** + * {@inheritDoc} + */ + protected void addNavDetailLink(boolean link, Content liNav) { if (link) { - writer.printHyperLink("", "method_detail", - ConfigurationImpl.getInstance().getText("doclet.navMethod")); + liNav.addContent(writer.getHyperLink("", "method_detail", + writer.getResource("doclet.navMethod"))); } else { - writer.printText("doclet.navMethod"); + liNav.addContent(writer.getResource("doclet.navMethod")); } } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java index 083adabef80..3f92c8e9a03 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java @@ -26,8 +26,10 @@ package com.sun.tools.doclets.formats.html; import java.io.*; +import java.util.*; import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; @@ -42,8 +44,6 @@ import com.sun.tools.doclets.internal.toolkit.util.*; public class NestedClassWriterImpl extends AbstractMemberWriter implements MemberSummaryWriter { - private boolean printedSummaryHeader = false; - public NestedClassWriterImpl(SubWriterHolderWriter writer, ClassDoc classdoc) { super(writer, classdoc); @@ -53,90 +53,17 @@ public class NestedClassWriterImpl extends AbstractMemberWriter super(writer); } - /** - * Write the classes summary header for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeMemberSummaryHeader(ClassDoc classDoc) { - printedSummaryHeader = true; - writer.println(""); - writer.println(); - writer.printSummaryHeader(this, classDoc); - } - - /** - * Write the classes summary footer for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeMemberSummaryFooter(ClassDoc classDoc) { - writer.printSummaryFooter(this, classDoc); - } - - /** - * Write the inherited classes summary header for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeInheritedMemberSummaryHeader(ClassDoc classDoc) { - if(! printedSummaryHeader){ - //We don't want inherited summary to not be under heading. - writeMemberSummaryHeader(classDoc); - writeMemberSummaryFooter(classDoc); - printedSummaryHeader = true; - } - writer.printInheritedSummaryHeader(this, classDoc); - } - /** * {@inheritDoc} */ - public void writeInheritedMemberSummary(ClassDoc classDoc, - ProgramElementDoc nestedClass, boolean isFirst, boolean isLast) { - writer.printInheritedSummaryMember(this, classDoc, nestedClass, isFirst); + public Content getMemberSummaryHeader(ClassDoc classDoc, + Content memberSummaryTree) { + memberSummaryTree.addContent(HtmlConstants.START_OF_NESTED_CLASS_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, classDoc, memberTree); + return memberTree; } - /** - * Write the inherited classes summary footer for the given class. - * - * @param classDoc the class the summary belongs to. - */ - public void writeInheritedMemberSummaryFooter(ClassDoc classDoc) { - writer.printInheritedSummaryFooter(this, classDoc); - writer.println(); - } - - /** - * Write the header for the nested class documentation. - * - * @param classDoc the class that the classes belong to. - */ - public void writeHeader(ClassDoc classDoc, String header) { - writer.anchor("nested class_detail"); - writer.printTableHeadingBackground(header); - } - - /** - * Write the nested class header for the given nested class. - * - * @param nestedClass the nested class being documented. - * @param isFirst the flag to indicate whether or not the nested class is the - * first to be documented. - */ - public void writeClassHeader(ClassDoc nestedClass, boolean isFirst) { - if (! isFirst) { - writer.printMemberHeader(); - writer.println(""); - } - writer.anchor(nestedClass.name()); - writer.h3(); - writer.print(nestedClass.name()); - writer.h3End(); - } - - - /** * Close the writer. */ @@ -148,17 +75,35 @@ public class NestedClassWriterImpl extends AbstractMemberWriter return VisibleMemberMap.INNERCLASSES; } - public void printSummaryLabel() { - writer.printText("doclet.Nested_Class_Summary"); + /** + * {@inheritDoc} + */ + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Nested_Class_Summary")); + memberTree.addContent(label); } - public void printTableSummary() { - writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + /** + * {@inheritDoc} + */ + public String getTableSummary() { + return configuration().getText("doclet.Member_Table_Summary", configuration().getText("doclet.Nested_Class_Summary"), - configuration().getText("doclet.nested_classes"))); + configuration().getText("doclet.nested_classes")); } - public void printSummaryTableHeader(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + public String getCaption() { + return configuration().getText("doclet.Nested_Classes"); + } + + /** + * {@inheritDoc} + */ + public String[] getSummaryTableHeader(ProgramElementDoc member) { String[] header; if (member.isInterface()) { header = new String[] { @@ -176,92 +121,95 @@ public class NestedClassWriterImpl extends AbstractMemberWriter configuration().getText("doclet.Description")) }; } - writer.summaryTableHeader(header, "col"); + return header; } - public void printSummaryAnchor(ClassDoc cd) { - writer.anchor("nested_class_summary"); + /** + * {@inheritDoc} + */ + public void addSummaryAnchor(ClassDoc cd, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor("nested_class_summary")); } - public void printInheritedSummaryAnchor(ClassDoc cd) { - writer.anchor("nested_classes_inherited_from_class_" + - cd.qualifiedName()); + /** + * {@inheritDoc} + */ + public void addInheritedSummaryAnchor(ClassDoc cd, Content inheritedTree) { + inheritedTree.addContent(writer.getMarkerAnchor( + "nested_classes_inherited_from_class_" + cd.qualifiedName())); } - public void printInheritedSummaryLabel(ClassDoc cd) { - String clslink = writer.getPreQualifiedClassLink( - LinkInfoImpl.CONTEXT_MEMBER, cd, false); - writer.strong(); - writer.printText(cd.isInterface() ? - "doclet.Nested_Classes_Interface_Inherited_From_Interface" : - "doclet.Nested_Classes_Interfaces_Inherited_From_Class", - clslink); - writer.strongEnd(); + /** + * {@inheritDoc} + */ + public void addInheritedSummaryLabel(ClassDoc cd, Content inheritedTree) { + Content classLink = new RawHtml(writer.getPreQualifiedClassLink( + LinkInfoImpl.CONTEXT_MEMBER, cd, false)); + Content label = new StringContent(cd.isInterface() ? + configuration().getText("doclet.Nested_Classes_Interface_Inherited_From_Interface") : + configuration().getText("doclet.Nested_Classes_Interfaces_Inherited_From_Class")); + Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING, + label); + labelHeading.addContent(writer.getSpace()); + labelHeading.addContent(classLink); + inheritedTree.addContent(labelHeading); } - protected void writeSummaryLink(int context, ClassDoc cd, ProgramElementDoc member) { - writer.strong(); - writer.printLink(new LinkInfoImpl(context, (ClassDoc)member, false)); - writer.strongEnd(); + /** + * {@inheritDoc} + */ + protected void addSummaryLink(int context, ClassDoc cd, ProgramElementDoc member, + Content tdSummary) { + Content strong = HtmlTree.STRONG(new RawHtml( + writer.getLink(new LinkInfoImpl(context, (ClassDoc)member, false)))); + Content code = HtmlTree.CODE(strong); + tdSummary.addContent(code); } - protected void writeInheritedSummaryLink(ClassDoc cd, - ProgramElementDoc member) { - writer.printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, - (ClassDoc)member, false)); + /** + * {@inheritDoc} + */ + protected void addInheritedSummaryLink(ClassDoc cd, + ProgramElementDoc member, Content linksTree) { + linksTree.addContent(new RawHtml( + writer.getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, + (ClassDoc)member, false)))); } - protected void printSummaryType(ProgramElementDoc member) { + /** + * {@inheritDoc} + */ + protected void addSummaryType(ProgramElementDoc member, + Content tdSummaryType) { ClassDoc cd = (ClassDoc)member; - printModifierAndType(cd, null); + addModifierAndType(cd, null, tdSummaryType); } - protected void printHeader(ClassDoc cd) { - // N.A. + /** + * {@inheritDoc} + */ + protected Content getDeprecatedLink(ProgramElementDoc member) { + return writer.getQualifiedClassLink(LinkInfoImpl.CONTEXT_MEMBER, + (ClassDoc)member); } - protected void printBodyHtmlEnd(ClassDoc cd) { - // N.A. - } - - protected void printMember(ProgramElementDoc member) { - // N.A. - } - - protected void writeDeprecatedLink(ProgramElementDoc member) { - writer.printQualifiedClassLink(LinkInfoImpl.CONTEXT_MEMBER, - (ClassDoc)member); - } - - protected void printNavSummaryLink(ClassDoc cd, boolean link) { + /** + * {@inheritDoc} + */ + protected Content getNavSummaryLink(ClassDoc cd, boolean link) { if (link) { - writer.printHyperLink("", (cd == null) ? "nested_class_summary": - "nested_classes_inherited_from_class_" + + return writer.getHyperLink("", (cd == null) ? "nested_class_summary": + "nested_classes_inherited_from_class_" + cd.qualifiedName(), - ConfigurationImpl.getInstance().getText("doclet.navNested")); + writer.getResource("doclet.navNested")); } else { - writer.printText("doclet.navNested"); + return writer.getResource("doclet.navNested"); } } - protected void printNavDetailLink(boolean link) { - } - - protected void printMemberLink(ProgramElementDoc member) { - } - - protected void printMembersSummaryLink(ClassDoc cd, ClassDoc icd, - boolean link) { - if (link) { - writer.printHyperLink(cd.name() + ".html", - (cd == icd)? - "nested_class_summary": - "nested_classes_inherited_from_class_" + - icd.qualifiedName(), - ConfigurationImpl.getInstance().getText( - "doclet.Nested_Class_Summary")); - } else { - writer.printText("doclet.Nested_Class_Summary"); - } + /** + * {@inheritDoc} + */ + protected void addNavDetailLink(boolean link, Content liNav) { } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageFrameWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageFrameWriter.java index 2f19b31e386..ace52703304 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageFrameWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageFrameWriter.java @@ -25,18 +25,20 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.util.*; -import com.sun.tools.doclets.internal.toolkit.*; - -import com.sun.javadoc.*; import java.io.*; import java.util.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.formats.html.markup.*; + /** * Class to generate file for each package contents in the left-hand bottom * frame. This will list all the Class Kinds in the package. A click on any * class-kind will update the right-hand frame with the clicked class-kind page. * * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class PackageFrameWriter extends HtmlDocletWriter { @@ -85,132 +87,107 @@ public class PackageFrameWriter extends HtmlDocletWriter { * @param packageDoc The package for which "pacakge-frame.html" is to be generated. */ public static void generate(ConfigurationImpl configuration, - PackageDoc packageDoc) { + PackageDoc packageDoc) { PackageFrameWriter packgen; try { packgen = new PackageFrameWriter(configuration, packageDoc); String pkgName = Util.getPackageName(packageDoc); - packgen.printHtmlHeader(pkgName, configuration.metakeywords.getMetaKeywords(packageDoc), false); - packgen.printPackageHeader(pkgName); - packgen.generateClassListing(); - packgen.printBodyHtmlEnd(); + Content body = packgen.getBody(false, packgen.getWindowTitle(pkgName)); + Content pkgNameContent = new StringContent(pkgName); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, HtmlStyle.bar, + packgen.getTargetPackageLink(packageDoc, "classFrame", pkgNameContent)); + body.addContent(heading); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.indexContainer); + packgen.addClassListing(div); + body.addContent(div); + packgen.printHtmlDocument( + configuration.metakeywords.getMetaKeywords(packageDoc), false, body); packgen.close(); } catch (IOException exc) { configuration.standardmessage.error( - "doclet.exception_encountered", - exc.toString(), OUTPUT_FILE_NAME); + "doclet.exception_encountered", + exc.toString(), OUTPUT_FILE_NAME); throw new DocletAbortException(); } } /** - * Generate class listing for all the classes in this package. Divide class + * Add class listing for all the classes in this package. Divide class * listing as per the class kind and generate separate listing for * Classes, Interfaces, Exceptions and Errors. + * + * @param contentTree the content tree to which the listing will be added */ - protected void generateClassListing() { + protected void addClassListing(Content contentTree) { Configuration config = configuration(); if (packageDoc.isIncluded()) { - generateClassKindListing(packageDoc.interfaces(), - configuration.getText("doclet.Interfaces")); - generateClassKindListing(packageDoc.ordinaryClasses(), - configuration.getText("doclet.Classes")); - generateClassKindListing(packageDoc.enums(), - configuration.getText("doclet.Enums")); - generateClassKindListing(packageDoc.exceptions(), - configuration.getText("doclet.Exceptions")); - generateClassKindListing(packageDoc.errors(), - configuration.getText("doclet.Errors")); - generateClassKindListing(packageDoc.annotationTypes(), - configuration.getText("doclet.AnnotationTypes")); + addClassKindListing(packageDoc.interfaces(), + getResource("doclet.Interfaces"), contentTree); + addClassKindListing(packageDoc.ordinaryClasses(), + getResource("doclet.Classes"), contentTree); + addClassKindListing(packageDoc.enums(), + getResource("doclet.Enums"), contentTree); + addClassKindListing(packageDoc.exceptions(), + getResource("doclet.Exceptions"), contentTree); + addClassKindListing(packageDoc.errors(), + getResource("doclet.Errors"), contentTree); + addClassKindListing(packageDoc.annotationTypes(), + getResource("doclet.AnnotationTypes"), contentTree); } else { String name = Util.getPackageName(packageDoc); - generateClassKindListing(config.classDocCatalog.interfaces(name), - configuration.getText("doclet.Interfaces")); - generateClassKindListing(config.classDocCatalog.ordinaryClasses(name), - configuration.getText("doclet.Classes")); - generateClassKindListing(config.classDocCatalog.enums(name), - configuration.getText("doclet.Enums")); - generateClassKindListing(config.classDocCatalog.exceptions(name), - configuration.getText("doclet.Exceptions")); - generateClassKindListing(config.classDocCatalog.errors(name), - configuration.getText("doclet.Errors")); - generateClassKindListing(config.classDocCatalog.annotationTypes(name), - configuration.getText("doclet.AnnotationTypes")); + addClassKindListing(config.classDocCatalog.interfaces(name), + getResource("doclet.Interfaces"), contentTree); + addClassKindListing(config.classDocCatalog.ordinaryClasses(name), + getResource("doclet.Classes"), contentTree); + addClassKindListing(config.classDocCatalog.enums(name), + getResource("doclet.Enums"), contentTree); + addClassKindListing(config.classDocCatalog.exceptions(name), + getResource("doclet.Exceptions"), contentTree); + addClassKindListing(config.classDocCatalog.errors(name), + getResource("doclet.Errors"), contentTree); + addClassKindListing(config.classDocCatalog.annotationTypes(name), + getResource("doclet.AnnotationTypes"), contentTree); } } /** - * Generate specific class kind listing. Also add label to the listing. + * Add specific class kind listing. Also add label to the listing. * - * @param arr Array of specific class kinds, namely Class or Interface or - * Exception or Error. - * @param label Label for the listing + * @param arr Array of specific class kinds, namely Class or Interface or Exception or Error + * @param labelContent content tree of the label to be added + * @param contentTree the content tree to which the class kind listing will be added */ - protected void generateClassKindListing(ClassDoc[] arr, String label) { + protected void addClassKindListing(ClassDoc[] arr, Content labelContent, + Content contentTree) { if(arr.length > 0) { Arrays.sort(arr); - printPackageTableHeader(); - fontSizeStyle("+1", "FrameHeadingFont"); boolean printedHeader = false; + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addAttr(HtmlAttr.TITLE, labelContent.toString()); for (int i = 0; i < arr.length; i++) { if (documentedClasses != null && - !documentedClasses.contains(arr[i])) { + !documentedClasses.contains(arr[i])) { continue; } if (!Util.isCoreClass(arr[i]) || ! - configuration.isGeneratedDoc(arr[i])) { + configuration.isGeneratedDoc(arr[i])) { continue; } if (!printedHeader) { - print(label); - fontEnd(); - println(" "); - fontStyle("FrameItemFont"); + Content heading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + true, labelContent); + contentTree.addContent(heading); printedHeader = true; } - br(); - printLink(new LinkInfoImpl( - LinkInfoImpl.PACKAGE_FRAME, - arr[i], - (arr[i].isInterface() ? - italicsText(arr[i].name()) : - arr[i].name()),"classFrame") - ); + Content link = new RawHtml (getLink(new LinkInfoImpl( + LinkInfoImpl.PACKAGE_FRAME, arr[i], + (arr[i].isInterface() ? italicsText(arr[i].name()) : + arr[i].name()),"classFrame"))); + Content li = HtmlTree.LI(link); + ul.addContent(li); } - fontEnd(); - printPackageTableFooter(); - println(); + contentTree.addContent(ul); } } - - /** - * Print the package link at the top of the class kind listing. Clicking - * this link, package-summary page will appear in the right hand frame. - * - * @param heading Top Heading to be used for the class kind listing. - */ - protected void printPackageHeader(String heading) { - fontSizeStyle("+1", "FrameTitleFont"); - printTargetPackageLink(packageDoc, "classFrame", heading); - fontEnd(); - } - - /** - * The table for the class kind listing. - */ - protected void printPackageTableHeader() { - table(); - tr(); - tdNowrap(); - } - - /** - * Closing Html tags for table of class kind listing. - */ - protected void printPackageTableFooter() { - tdEnd(); - trEnd(); - tableEnd(); - } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java index 60f853f2868..a7944122ae2 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java @@ -25,10 +25,11 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.util.*; - -import com.sun.javadoc.*; import java.io.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Generate the package index for the left-hand frame in the generated output. @@ -58,7 +59,7 @@ public class PackageIndexFrameWriter extends AbstractPackageIndexWriter { String filename = "overview-frame.html"; try { packgen = new PackageIndexFrameWriter(configuration, filename); - packgen.generatePackageIndexFile("doclet.Window_Overview", false); + packgen.buildPackageIndexFile("doclet.Window_Overview", false); packgen.close(); } catch (IOException exc) { configuration.standardmessage.error( @@ -69,114 +70,86 @@ public class PackageIndexFrameWriter extends AbstractPackageIndexWriter { } /** - * Print each package name on separate rows. - * - * @param pd PackageDoc + * {@inheritDoc} */ - protected void printIndexRow(PackageDoc pd) { - fontStyle("FrameItemFont"); - if (pd.name().length() > 0) { - print(getHyperLink(pathString(pd, "package-frame.html"), "", - pd.name(), false, "", "", "packageFrame")); - } else { - print(getHyperLink("package-frame.html", "", "<unnamed package>", - false, "", "", "packageFrame")); + protected void addPackagesList(PackageDoc[] packages, String text, + String tableSummary, Content body) { + Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, + packagesLabel); + Content div = HtmlTree.DIV(HtmlStyle.indexContainer, heading); + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addAttr(HtmlAttr.TITLE, packagesLabel.toString()); + for(int i = 0; i < packages.length; i++) { + if (packages[i] != null) { + ul.addContent(getPackage(packages[i])); + } } - fontEnd(); - br(); + div.addContent(ul); + body.addContent(div); } /** - * Print the "-packagesheader" string in strong format, at top of the page, - * if it is not the empty string. Otherwise print the "-header" string. - * Despite the name, there is actually no navigation bar for this page. + * Gets each package name as a separate link. + * + * @param pd PackageDoc + * @return content for the package link */ - protected void printNavigationBarHeader() { - printTableHeader(true); - fontSizeStyle("+1", "FrameTitleFont"); - if (configuration.packagesheader.length() > 0) { - strong(replaceDocRootDir(configuration.packagesheader)); + protected Content getPackage(PackageDoc pd) { + Content packageLinkContent; + Content packageLabel; + if (pd.name().length() > 0) { + packageLabel = getPackageLabel(pd.name()); + packageLinkContent = getHyperLink(pathString(pd, + "package-frame.html"), "", packageLabel, "", + "packageFrame"); } else { - strong(replaceDocRootDir(configuration.header)); + packageLabel = new RawHtml("<unnamed package>"); + packageLinkContent = getHyperLink("package-frame.html", + "", packageLabel, "", "packageFrame"); } - fontEnd(); - printTableFooter(true); + Content li = HtmlTree.LI(packageLinkContent); + return li; + } + + /** + * {@inheritDoc} + */ + protected void addNavigationBarHeader(Content body) { + Content headerContent; + if (configuration.packagesheader.length() > 0) { + headerContent = new RawHtml(replaceDocRootDir(configuration.packagesheader)); + } else { + headerContent = new RawHtml(replaceDocRootDir(configuration.header)); + } + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.bar, headerContent); + body.addContent(heading); } /** * Do nothing as there is no overview information in this page. */ - protected void printOverviewHeader() { + protected void addOverviewHeader(Content body) { } /** - * Print Html "table" tag for the package index format. + * Adds "All Classes" link for the top of the left-hand frame page to the + * documentation tree. * - * @param text Text string will not be used in this method. + * @param body the Content object to which the all classes link should be added */ - protected void printIndexHeader(String text, String tableSummary) { - printTableHeader(false); + protected void addAllClassesLink(Content body) { + Content linkContent = getHyperLink("allclasses-frame.html", "", + allclassesLabel, "", "packageFrame"); + Content div = HtmlTree.DIV(HtmlStyle.indexHeader, linkContent); + body.addContent(div); } /** - * Print Html closing "table" tag at the end of the package index. + * {@inheritDoc} */ - protected void printIndexFooter() { - printTableFooter(false); - } - - /** - * Print "All Classes" link at the top of the left-hand frame page. - */ - protected void printAllClassesPackagesLink() { - fontStyle("FrameItemFont"); - print(getHyperLink("allclasses-frame.html", "", - configuration.getText("doclet.All_Classes"), false, "", "", - "packageFrame")); - fontEnd(); - p(); - fontSizeStyle("+1", "FrameHeadingFont"); - printText("doclet.Packages"); - fontEnd(); - br(); - } - - /** - * Just print some space, since there is no navigation bar for this page. - */ - protected void printNavigationBarFooter() { - p(); - space(); - } - - /** - * Print Html closing tags for the table for package index. - * - * @param isHeading true if this is a table for a heading. - */ - private void printTableFooter(boolean isHeading) { - if (isHeading) { - thEnd(); - } else { - tdEnd(); - } - trEnd(); - tableEnd(); - } - - /** - * Print Html tags for the table for package index. - * - * @param isHeading true if this is a table for a heading. - */ - private void printTableHeader(boolean isHeading) { - table(); - tr(); - if (isHeading) { - thAlignNowrap("left"); - } else { - tdNowrap(); - } - + protected void addNavigationBarFooter(Content body) { + Content p = HtmlTree.P(getSpace()); + body.addContent(p); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java index 4088c14f1be..6a286c71ccb 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java @@ -25,10 +25,12 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.util.*; -import com.sun.javadoc.*; import java.io.*; import java.util.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Generate the package index page "overview-summary.html" for the right-hand @@ -83,7 +85,7 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { String filename = "overview-summary.html"; try { packgen = new PackageIndexWriter(configuration, filename); - packgen.generatePackageIndexFile("doclet.Window_Overview_Summary", true); + packgen.buildPackageIndexFile("doclet.Window_Overview_Summary", true); packgen.close(); } catch (IOException exc) { configuration.standardmessage.error( @@ -94,124 +96,140 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { } /** - * Print each package in separate rows in the index table. Generate link - * to each package. - * - * @param pkg Package to which link is to be generated. - */ - protected void printIndexRow(PackageDoc pkg) { - if(pkg != null && pkg.name().length() > 0) { - trBgcolorStyle("white", "TableRowColor"); - summaryRow(20); - strong(); - printPackageLink(pkg, Util.getPackageName(pkg), false); - strongEnd(); - summaryRowEnd(); - summaryRow(0); - printSummaryComment(pkg); - summaryRowEnd(); - trEnd(); - } - } - - /** - * Depending upon the grouping information and their titles, generate + * Depending upon the grouping information and their titles, add * separate table indices for each package group. + * + * @param body the documentation tree to which the index will be added */ - protected void generateIndex() { + protected void addIndex(Content body) { for (int i = 0; i < groupList.size(); i++) { String groupname = groupList.get(i); List list = groupPackageMap.get(groupname); if (list != null && list.size() > 0) { - printIndexContents(list.toArray(new PackageDoc[list.size()]), - groupname, - configuration.getText("doclet.Member_Table_Summary", - groupname, - configuration.getText("doclet.packages"))); + addIndexContents(list.toArray(new PackageDoc[list.size()]), + groupname, configuration.getText("doclet.Member_Table_Summary", + groupname, configuration.getText("doclet.packages")), body); } } } /** - * Print the overview summary comment for this documentation. Print one line + * {@inheritDoc} + */ + protected void addPackagesList(PackageDoc[] packages, String text, + String tableSummary, Content body) { + Content table = HtmlTree.TABLE(HtmlStyle.overviewSummary, 0, 3, 0, tableSummary, + getTableCaption(text)); + table.addContent(getSummaryTableHeader(packageTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + addPackagesList(packages, tbody); + table.addContent(tbody); + Content div = HtmlTree.DIV(HtmlStyle.contentContainer, table); + body.addContent(div); + } + + /** + * Adds list of packages in the index table. Generate link to each package. + * + * @param packages Packages to which link is to be generated + * @param tbody the documentation tree to which the list will be added + */ + protected void addPackagesList(PackageDoc[] packages, Content tbody) { + for (int i = 0; i < packages.length; i++) { + if (packages[i] != null && packages[i].name().length() > 0) { + Content packageLinkContent = getPackageLink(packages[i], + getPackageName(packages[i])); + Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, packageLinkContent); + HtmlTree tdSummary = new HtmlTree(HtmlTag.TD); + tdSummary.addStyle(HtmlStyle.colLast); + addSummaryComment(packages[i], tdSummary); + HtmlTree tr = HtmlTree.TR(tdPackage); + tr.addContent(tdSummary); + if (i%2 == 0) + tr.addStyle(HtmlStyle.altColor); + else + tr.addStyle(HtmlStyle.rowColor); + tbody.addContent(tr); + } + } + } + + /** + * Adds the overview summary comment for this documentation. Add one line * summary at the top of the page and generate a link to the description, - * which is generated at the end of this page. + * which is added at the end of this page. + * + * @param body the documentation tree to which the overview header will be added */ - protected void printOverviewHeader() { + protected void addOverviewHeader(Content body) { if (root.inlineTags().length > 0) { - printSummaryComment(root); - p(); - strong(configuration.getText("doclet.See")); - br(); - printNbsps(); - printHyperLink("", "overview_description", - configuration.getText("doclet.Description"), true); - p(); + HtmlTree p = new HtmlTree(HtmlTag.P); + p.addStyle(HtmlStyle.subTitle); + addSummaryComment(root, p); + Content div = HtmlTree.DIV(HtmlStyle.header, p); + Content see = seeLabel; + see.addContent(" "); + Content descPara = HtmlTree.P(see); + Content descLink = getHyperLink("", "overview_description", + descriptionLabel, "", ""); + descPara.addContent(descLink); + div.addContent(descPara); + body.addContent(div); } } /** - * Print Html tags for the table for this package index. - */ - protected void printIndexHeader(String text, String tableSummary) { - tableIndexSummary(tableSummary); - tableCaptionStart(); - print(text); - tableCaptionEnd(); - summaryTableHeader(packageTableHeader, "col"); - } - - /** - * Print Html closing tags for the table for this package index. - */ - protected void printIndexFooter() { - tableEnd(); - p(); - space(); - } - - /** - * Print the overview comment as provided in the file specified by the + * Adds the overview comment as provided in the file specified by the * "-overview" option on the command line. + * + * @param htmltree the documentation tree to which the overview comment will + * be added */ - protected void printOverviewComment() { + protected void addOverviewComment(Content htmltree) { if (root.inlineTags().length > 0) { - anchor("overview_description"); - p(); - printInlineComment(root); - p(); + htmltree.addContent(getMarkerAnchor("overview_description")); + HtmlTree p = new HtmlTree(HtmlTag.P); + p.addStyle(HtmlStyle.subTitle); + addInlineComment(root, p); + htmltree.addContent(p); } } /** - * Call {@link #printOverviewComment()} and then genrate the tag information - * as provided in the file specified by the "-overview" option on the - * command line. + * Adds the tag information as provided in the file specified by the + * "-overview" option on the command line. + * + * @param body the documentation tree to which the overview will be added */ - protected void printOverview() throws IOException { - printOverviewComment(); - printTags(root); + protected void addOverview(Content body) throws IOException { + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.footer); + addOverviewComment(div); + addTagsInfo(root, div); + body.addContent(div); } /** - * Print the top text (from the -top option), the upper + * Adds the top text (from the -top option), the upper * navigation bar, and then the title (from the"-title" * option), at the top of page. + * + * @body the documentation tree to which the navigation bar header will be added */ - protected void printNavigationBarHeader() { - printTop(); - navLinks(true); - hr(); - printConfigurationTitle(); + protected void addNavigationBarHeader(Content body) { + addTop(body); + addNavLinks(true, body); + addConfigurationTitle(body); } /** - * Print the lower navigation bar and the bottom text + * Adds the lower navigation bar and the bottom text * (from the -bottom option) at the bottom of page. + * + * @param the documentation tree to which the navigation bar footer will be added */ - protected void printNavigationBarFooter() { - hr(); - navLinks(false); - printBottom(); + protected void addNavigationBarFooter(Content body) { + addNavLinks(false, body); + addBottom(body); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java index 957dda4d38e..48e2e7324ab 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageTreeWriter.java @@ -29,12 +29,15 @@ import java.io.*; import com.sun.javadoc.*; import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; /** * Class to generate Tree page for a package. The name of the file generated is * "package-tree.html" and it is generated in the respective package directory. * * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class PackageTreeWriter extends AbstractTreeWriter { @@ -107,94 +110,96 @@ public class PackageTreeWriter extends AbstractTreeWriter { * Generate a separate tree file for each package. */ protected void generatePackageTreeFile() throws IOException { - printHtmlHeader(packagedoc.name() + " " - + configuration.getText("doclet.Window_Class_Hierarchy"), null, true); - - printPackageTreeHeader(); - + Content body = getPackageTreeHeader(); + Content headContent = getResource("doclet.Hierarchy_For_Package", + Util.getPackageName(packagedoc)); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, false, + HtmlStyle.title, headContent); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); if (configuration.packages.length > 1) { - printLinkToMainTree(); + addLinkToMainTree(div); } - - generateTree(classtree.baseclasses(), "doclet.Class_Hierarchy"); - generateTree(classtree.baseinterfaces(), "doclet.Interface_Hierarchy"); - generateTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy"); - generateTree(classtree.baseEnums(), "doclet.Enum_Hierarchy"); - - printPackageTreeFooter(); - printBottom(); - printBodyHtmlEnd(); + body.addContent(div); + HtmlTree divTree = new HtmlTree(HtmlTag.DIV); + divTree.addStyle(HtmlStyle.contentContainer); + addTree(classtree.baseclasses(), "doclet.Class_Hierarchy", divTree); + addTree(classtree.baseinterfaces(), "doclet.Interface_Hierarchy", divTree); + addTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy", divTree); + addTree(classtree.baseEnums(), "doclet.Enum_Hierarchy", divTree); + body.addContent(divTree); + addNavLinks(false, body); + addBottom(body); + printHtmlDocument(null, true, body); } /** - * Print the navigation bar header for the package tree file. + * Get the package tree header. + * + * @return a content tree for the header */ - protected void printPackageTreeHeader() { - printTop(); - navLinks(true); - hr(); - center(); - h2(configuration.getText("doclet.Hierarchy_For_Package", - Util.getPackageName(packagedoc))); - centerEnd(); + protected Content getPackageTreeHeader() { + String title = packagedoc.name() + " " + + configuration.getText("doclet.Window_Class_Hierarchy"); + Content bodyTree = getBody(true, getWindowTitle(title)); + addTop(bodyTree); + addNavLinks(true, bodyTree); + return bodyTree; } /** - * Generate a link to the tree for all the packages. + * Add a link to the tree for all the packages. + * + * @param div the content tree to which the link will be added */ - protected void printLinkToMainTree() { - dl(); - dt(); - strongText("doclet.Package_Hierarchies"); - dtEnd(); - dd(); - navLinkMainTree(configuration.getText("doclet.All_Packages")); - ddEnd(); - dlEnd(); - hr(); + protected void addLinkToMainTree(Content div) { + Content span = HtmlTree.SPAN(HtmlStyle.strong, + getResource("doclet.Package_Hierarchies")); + div.addContent(span); + HtmlTree ul = new HtmlTree (HtmlTag.UL); + ul.addStyle(HtmlStyle.horizontal); + ul.addContent(getNavLinkMainTree(configuration.getText("doclet.All_Packages"))); + div.addContent(ul); } /** - * Print the navigation bar footer for the package tree file. + * Get link for the previous package tree file. + * + * @return a content tree for the link */ - protected void printPackageTreeFooter() { - hr(); - navLinks(false); - } - - /** - * Link for the previous package tree file. - */ - protected void navLinkPrevious() { + protected Content getNavLinkPrevious() { if (prev == null) { - navLinkPrevious(null); + return getNavLinkPrevious(null); } else { String path = DirectoryManager.getRelativePath(packagedoc.name(), - prev.name()); - navLinkPrevious(path + "package-tree.html"); + prev.name()); + return getNavLinkPrevious(path + "package-tree.html"); } } /** - * Link for the next package tree file. + * Get link for the next package tree file. + * + * @return a content tree for the link */ - protected void navLinkNext() { + protected Content getNavLinkNext() { if (next == null) { - navLinkNext(null); + return getNavLinkNext(null); } else { String path = DirectoryManager.getRelativePath(packagedoc.name(), - next.name()); - navLinkNext(path + "package-tree.html"); + next.name()); + return getNavLinkNext(path + "package-tree.html"); } } /** - * Link to the package summary page for the package of this tree. + * Get link to the package summary page for the package of this tree. + * + * @return a content tree for the package link */ - protected void navLinkPackage() { - navCellStart(); - printHyperLink("package-summary.html", "", configuration.getText("doclet.Package"), - true, "NavBarFont1"); - navCellEnd(); + protected Content getNavLinkPackage() { + Content linkContent = getHyperLink("package-summary.html", "", + packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java index 57e2f02995d..4a454d3b10e 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java @@ -25,10 +25,12 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.util.*; -import com.sun.javadoc.*; import java.io.*; import java.util.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; /** * Generate package usage information. @@ -106,49 +108,74 @@ public class PackageUseWriter extends SubWriterHolderWriter { /** - * Print the class use list. + * Generate the package use list. */ protected void generatePackageUseFile() throws IOException { - printPackageUseHeader(); - + Content body = getPackageUseHeader(); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.contentContainer); if (usingPackageToUsedClasses.isEmpty()) { - printText("doclet.ClassUse_No.usage.of.0", pkgdoc.name()); - p(); + div.addContent(getResource( + "doclet.ClassUse_No.usage.of.0", pkgdoc.name())); } else { - generatePackageUse(); + addPackageUse(div); } - - printPackageUseFooter(); + body.addContent(div); + addNavLinks(false, body); + addBottom(body); + printHtmlDocument(null, true, body); } /** - * Print the class use list. + * Add the package use information. + * + * @param contentTree the content tree to which the package use information will be added */ - protected void generatePackageUse() throws IOException { + protected void addPackageUse(Content contentTree) throws IOException { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); if (configuration.packages.length > 1) { - generatePackageList(); + addPackageList(ul); } - generateClassList(); + addClassList(ul); + contentTree.addContent(ul); } - protected void generatePackageList() throws IOException { - tableIndexSummary(useTableSummary); - tableCaptionStart(); - printText("doclet.ClassUse_Packages.that.use.0", - getPackageLink(pkgdoc, Util.getPackageName(pkgdoc), false)); - tableCaptionEnd(); - summaryTableHeader(packageTableHeader, "col"); + /** + * Add the list of packages that use the given package. + * + * @param contentTree the content tree to which the package list will be added + */ + protected void addPackageList(Content contentTree) throws IOException { + Content table = HtmlTree.TABLE(0, 3, 0, useTableSummary, + getTableCaption(configuration().getText( + "doclet.ClassUse_Packages.that.use.0", + getPackageLinkString(pkgdoc, Util.getPackageName(pkgdoc), false)))); + table.addContent(getSummaryTableHeader(packageTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); Iterator it = usingPackageToUsedClasses.keySet().iterator(); - while (it.hasNext()) { + for (int i = 0; it.hasNext(); i++) { PackageDoc pkg = configuration.root.packageNamed(it.next()); - generatePackageUse(pkg); + HtmlTree tr = new HtmlTree(HtmlTag.TR); + if (i % 2 == 0) { + tr.addStyle(HtmlStyle.altColor); + } else { + tr.addStyle(HtmlStyle.rowColor); + } + addPackageUse(pkg, tr); + tbody.addContent(tr); } - tableEnd(); - space(); - p(); + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + contentTree.addContent(li); } - protected void generateClassList() throws IOException { + /** + * Add the list of classes that use the given package. + * + * @param contentTree the content tree to which the class list will be added + */ + protected void addClassList(Content contentTree) throws IOException { String[] classTableHeader = new String[] { configuration.getText("doclet.0_and_1", configuration.getText("doclet.Class"), @@ -158,117 +185,126 @@ public class PackageUseWriter extends SubWriterHolderWriter { while (itp.hasNext()) { String packageName = itp.next(); PackageDoc usingPackage = configuration.root.packageNamed(packageName); + HtmlTree li = new HtmlTree(HtmlTag.LI); + li.addStyle(HtmlStyle.blockList); if (usingPackage != null) { - anchor(usingPackage.name()); + li.addContent(getMarkerAnchor(usingPackage.name())); } - tableIndexSummary(configuration.getText("doclet.Use_Table_Summary", - configuration.getText("doclet.classes"))); - tableCaptionStart(); - printText("doclet.ClassUse_Classes.in.0.used.by.1", - getPackageLink(pkgdoc, Util.getPackageName(pkgdoc), false), - getPackageLink(usingPackage,Util.getPackageName(usingPackage), false)); - tableCaptionEnd(); - summaryTableHeader(classTableHeader, "col"); + String tableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.classes")); + Content table = HtmlTree.TABLE(0, 3, 0, tableSummary, + getTableCaption(configuration().getText( + "doclet.ClassUse_Classes.in.0.used.by.1", + getPackageLinkString(pkgdoc, Util.getPackageName(pkgdoc), false), + getPackageLinkString(usingPackage,Util.getPackageName(usingPackage), false)))); + table.addContent(getSummaryTableHeader(classTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); Iterator itc = usingPackageToUsedClasses.get(packageName).iterator(); - while (itc.hasNext()) { - printClassRow(itc.next(), packageName); + for (int i = 0; itc.hasNext(); i++) { + HtmlTree tr = new HtmlTree(HtmlTag.TR); + if (i % 2 == 0) { + tr.addStyle(HtmlStyle.altColor); + } else { + tr.addStyle(HtmlStyle.rowColor); + } + addClassRow(itc.next(), packageName, tr); + tbody.addContent(tr); } - tableEnd(); - space(); - p(); + table.addContent(tbody); + li.addContent(table); + contentTree.addContent(li); } } - protected void printClassRow(ClassDoc usedClass, String packageName) { + /** + * Add a row for the class that uses the given package. + * + * @param usedClass the class that uses the given package + * @param packageName the name of the package to which the class belongs + * @param contentTree the content tree to which the row will be added + */ + protected void addClassRow(ClassDoc usedClass, String packageName, + Content contentTree) { String path = pathString(usedClass, - "class-use/" + usedClass.name() + ".html"); - - trBgcolorStyle("white", "TableRowColor"); - summaryRow(0); - strong(); - printHyperLink(path, packageName, usedClass.name(), true); - strongEnd(); - println(); br(); - printNbsps(); - printIndexComment(usedClass); - summaryRowEnd(); - trEnd(); + "class-use/" + usedClass.name() + ".html"); + Content td = HtmlTree.TD(HtmlStyle.colOne, + getHyperLink(path, packageName, new StringContent(usedClass.name()))); + addIndexComment(usedClass, td); + contentTree.addContent(td); } /** - * Print the package use list. + * Add the package use information. + * + * @param pkg the package that used the given package + * @param contentTree the content tree to which the information will be added */ - protected void generatePackageUse(PackageDoc pkg) throws IOException { - trBgcolorStyle("white", "TableRowColor"); - summaryRow(0); - //Just want an anchor here. - printHyperLink("", pkg.name(), Util.getPackageName(pkg), true); - summaryRowEnd(); - summaryRow(0); - if (pkg != null) { - printSummaryComment(pkg); - } - space(); - summaryRowEnd(); - trEnd(); + protected void addPackageUse(PackageDoc pkg, Content contentTree) throws IOException { + Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, + getHyperLink("", pkg.name(), new StringContent(Util.getPackageName(pkg)))); + contentTree.addContent(tdFirst); + HtmlTree tdLast = new HtmlTree(HtmlTag.TD); + tdLast.addStyle(HtmlStyle.colLast); + if (pkg != null) + addSummaryComment(pkg, tdLast); + else + tdLast.addContent(getSpace()); + contentTree.addContent(tdLast); } /** - * Print the header for the class use Listing. + * Get the header for the package use listing. + * + * @return a content tree representing the package use header */ - protected void printPackageUseHeader() { - String packageLabel = configuration.getText("doclet.Package"); + protected Content getPackageUseHeader() { + String packageText = configuration.getText("doclet.Package"); String name = pkgdoc.name(); - printHtmlHeader(configuration.getText("doclet.Window_ClassUse_Header", - packageLabel, name), null, true); - printTop(); - navLinks(true); - hr(); - center(); - h2(); - strongText("doclet.ClassUse_Title", packageLabel, name); - h2End(); - centerEnd(); + String title = configuration.getText("doclet.Window_ClassUse_Header", + packageText, name); + Content bodyTree = getBody(true, getWindowTitle(title)); + addTop(bodyTree); + addNavLinks(true, bodyTree); + Content headContent = getResource("doclet.ClassUse_Title", packageText, name); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.title, headContent); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + bodyTree.addContent(div); + return bodyTree; } /** - * Print the footer for the class use Listing. + * Get this package link. + * + * @return a content tree for the package link */ - protected void printPackageUseFooter() { - hr(); - navLinks(false); - printBottom(); - printBodyHtmlEnd(); - } - - - /** - * Print this package link - */ - protected void navLinkPackage() { - navCellStart(); - printHyperLink("package-summary.html", "", configuration.getText("doclet.Package"), - true, "NavBarFont1"); - navCellEnd(); + protected Content getNavLinkPackage() { + Content linkContent = getHyperLink("package-summary.html", "", + packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; } /** - * Print class use link + * Get the use link. + * + * @return a content tree for the use link */ - protected void navLinkClassUse() { - navCellRevStart(); - fontStyle("NavBarFont1Rev"); - strongText("doclet.navClassUse"); - fontEnd(); - navCellEnd(); + protected Content getNavLinkClassUse() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, useLabel); + return li; } - protected void navLinkTree() { - navCellStart(); - printHyperLink("package-tree.html", "", configuration.getText("doclet.Tree"), - true, "NavBarFont1"); - navCellEnd(); + /** + * Get the tree link. + * + * @return a content tree for the tree link + */ + protected Content getNavLinkTree() { + Content linkContent = getHyperLink("package-tree.html", "", + treeLabel); + Content li = HtmlTree.LI(linkContent); + return li; } - } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java index b7cef1b661e..9ba67cee6a9 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java @@ -25,12 +25,12 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.*; -import com.sun.tools.doclets.internal.toolkit.util.*; - -import com.sun.javadoc.*; import java.io.*; import java.util.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Class to generate file for each package contents in the right-hand @@ -98,189 +98,206 @@ public class PackageWriterImpl extends HtmlDocletWriter /** * {@inheritDoc} */ - public void writeSummaryHeader() {} + public Content getPackageHeader(String heading) { + String pkgName = packageDoc.name(); + Content bodyTree = getBody(true, getWindowTitle(pkgName)); + addTop(bodyTree); + addNavLinks(true, bodyTree); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.header); + Content annotationContent = new HtmlTree(HtmlTag.P); + addAnnotationInfo(packageDoc, annotationContent); + div.addContent(annotationContent); + Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.title, packageLabel); + tHeading.addContent(getSpace()); + Content packageHead = new RawHtml(heading); + tHeading.addContent(packageHead); + div.addContent(tHeading); + if (packageDoc.inlineTags().length > 0 && ! configuration.nocomment) { + HtmlTree p = new HtmlTree(HtmlTag.P); + p.addStyle(HtmlStyle.subTitle); + addSummaryComment(packageDoc, p); + div.addContent(p); + Content space = getSpace(); + Content descLink = getHyperLink("", "package_description", + descriptionLabel, "", ""); + Content descPara = new HtmlTree(HtmlTag.P, seeLabel, space, descLink); + div.addContent(descPara); + } + bodyTree.addContent(div); + return bodyTree; + } /** * {@inheritDoc} */ - public void writeSummaryFooter() {} + public Content getContentHeader() { + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.contentContainer); + return div; + } /** * {@inheritDoc} */ - public void writeClassesSummary(ClassDoc[] classes, String label, String tableSummary, String[] tableHeader) { + public Content getSummaryHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * {@inheritDoc} + */ + public void addClassesSummary(ClassDoc[] classes, String label, + String tableSummary, String[] tableHeader, Content summaryContentTree) { if(classes.length > 0) { Arrays.sort(classes); - tableIndexSummary(tableSummary); - boolean printedHeading = false; + Content caption = getTableCaption(label); + Content table = HtmlTree.TABLE(HtmlStyle.packageSummary, 0, 3, 0, + tableSummary, caption); + table.addContent(getSummaryTableHeader(tableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); for (int i = 0; i < classes.length; i++) { - if (!printedHeading) { - printTableCaption(label); - printFirstRow(tableHeader); - printedHeading = true; - } if (!Util.isCoreClass(classes[i]) || !configuration.isGeneratedDoc(classes[i])) { continue; } - trBgcolorStyle("white", "TableRowColor"); - summaryRow(15); - strong(); - printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_PACKAGE, - classes[i], false)); - strongEnd(); - summaryRowEnd(); - summaryRow(0); + Content classContent = new RawHtml(getLink(new LinkInfoImpl( + LinkInfoImpl.CONTEXT_PACKAGE, classes[i], false))); + Content tdClass = HtmlTree.TD(HtmlStyle.colFirst, classContent); + HtmlTree tr = HtmlTree.TR(tdClass); + if (i%2 == 0) + tr.addStyle(HtmlStyle.altColor); + else + tr.addStyle(HtmlStyle.rowColor); + HtmlTree tdClassDescription = new HtmlTree(HtmlTag.TD); + tdClassDescription.addStyle(HtmlStyle.colLast); if (Util.isDeprecated(classes[i])) { - strongText("doclet.Deprecated"); + tdClassDescription.addContent(deprecatedLabel); if (classes[i].tags("deprecated").length > 0) { - space(); - printSummaryDeprecatedComment(classes[i], - classes[i].tags("deprecated")[0]); + addSummaryDeprecatedComment(classes[i], + classes[i].tags("deprecated")[0], tdClassDescription); } - } else { - printSummaryComment(classes[i]); } - summaryRowEnd(); - trEnd(); + else + addSummaryComment(classes[i], tdClassDescription); + tr.addContent(tdClassDescription); + tbody.addContent(tr); } - tableEnd(); - println(" "); - p(); + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + summaryContentTree.addContent(li); } } - /** - * Print the table caption for the class-listing. - * - * @param label label for the Class kind listing. - */ - protected void printTableCaption(String label) { - tableCaptionStart(); - print(label); - tableCaptionEnd(); - } - - /** - * Print the table heading for the class-listing. - * - * @param tableHeader table header string for the Class listing. - */ - protected void printFirstRow(String[] tableHeader) { - summaryTableHeader(tableHeader, "col"); - } - /** * {@inheritDoc} */ - public void writePackageDescription() { + public void addPackageDescription(Content packageContentTree) { if (packageDoc.inlineTags().length > 0) { - anchor("package_description"); - h2(configuration.getText("doclet.Package_Description", packageDoc.name())); - p(); - printInlineComment(packageDoc); - p(); + packageContentTree.addContent(getMarkerAnchor("package_description")); + Content h2Content = new StringContent( + configuration.getText("doclet.Package_Description", + packageDoc.name())); + packageContentTree.addContent(HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, + true, h2Content)); + addInlineComment(packageDoc, packageContentTree); } } /** * {@inheritDoc} */ - public void writePackageTags() { - printTags(packageDoc); + public void addPackageTags(Content packageContentTree) { + addTagsInfo(packageDoc, packageContentTree); } /** * {@inheritDoc} */ - public void writePackageHeader(String heading) { - String pkgName = packageDoc.name(); - printHtmlHeader(pkgName, - configuration.metakeywords.getMetaKeywords(packageDoc), true); - printTop(); - navLinks(true); - hr(); - writeAnnotationInfo(packageDoc); - h2(configuration.getText("doclet.Package") + " " + heading); - if (packageDoc.inlineTags().length > 0 && ! configuration.nocomment) { - printSummaryComment(packageDoc); - p(); - strong(configuration.getText("doclet.See")); - br(); - printNbsps(); - printHyperLink("", "package_description", - configuration.getText("doclet.Description"), true); - p(); - } + public void addPackageFooter(Content contentTree) { + addNavLinks(false, contentTree); + addBottom(contentTree); } /** * {@inheritDoc} */ - public void writePackageFooter() { - hr(); - navLinks(false); - printBottom(); - printBodyHtmlEnd(); + public void printDocument(Content contentTree) { + printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageDoc), + true, contentTree); } /** - * Print "Use" link for this pacakge in the navigation bar. + * Get "Use" link for this pacakge in the navigation bar. + * + * @return a content tree for the class use link */ - protected void navLinkClassUse() { - navCellStart(); - printHyperLink("package-use.html", "", configuration.getText("doclet.navClassUse"), - true, "NavBarFont1"); - navCellEnd(); + protected Content getNavLinkClassUse() { + Content useLink = getHyperLink("package-use.html", "", + useLabel, "", ""); + Content li = HtmlTree.LI(useLink); + return li; } /** - * Print "PREV PACKAGE" link in the navigation bar. + * Get "PREV PACKAGE" link in the navigation bar. + * + * @return a content tree for the previous link */ - protected void navLinkPrevious() { + public Content getNavLinkPrevious() { + Content li; if (prev == null) { - printText("doclet.Prev_Package"); + li = HtmlTree.LI(prevpackageLabel); } else { String path = DirectoryManager.getRelativePath(packageDoc.name(), prev.name()); - printHyperLink(path + "package-summary.html", "", - configuration.getText("doclet.Prev_Package"), true); + li = HtmlTree.LI(getHyperLink(path + "package-summary.html", "", + prevpackageLabel, "", "")); } + return li; } /** - * Print "NEXT PACKAGE" link in the navigation bar. + * Get "NEXT PACKAGE" link in the navigation bar. + * + * @return a content tree for the next link */ - protected void navLinkNext() { + public Content getNavLinkNext() { + Content li; if (next == null) { - printText("doclet.Next_Package"); + li = HtmlTree.LI(nextpackageLabel); } else { String path = DirectoryManager.getRelativePath(packageDoc.name(), next.name()); - printHyperLink(path + "package-summary.html", "", - configuration.getText("doclet.Next_Package"), true); + li = HtmlTree.LI(getHyperLink(path + "package-summary.html", "", + nextpackageLabel, "", "")); } + return li; } /** - * Print "Tree" link in the navigation bar. This will be link to the package + * Get "Tree" link in the navigation bar. This will be link to the package * tree file. + * + * @return a content tree for the tree link */ - protected void navLinkTree() { - navCellStart(); - printHyperLink("package-tree.html", "", configuration.getText("doclet.Tree"), - true, "NavBarFont1"); - navCellEnd(); + protected Content getNavLinkTree() { + Content useLink = getHyperLink("package-tree.html", "", + treeLabel, "", ""); + Content li = HtmlTree.LI(useLink); + return li; } /** * Highlight "Package" in the navigation bar, as this is the package page. + * + * @return a content tree for the package link */ - protected void navLinkPackage() { - navCellRevStart(); - fontStyle("NavBarFont1Rev"); - strongText("doclet.Package"); - fontEnd(); - navCellEnd(); + protected Content getNavLinkPackage() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, packageLabel); + return li; } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SerializedFormWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SerializedFormWriterImpl.java index e06a5a1f959..36721b53e86 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SerializedFormWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SerializedFormWriterImpl.java @@ -25,8 +25,10 @@ package com.sun.tools.doclets.formats.html; -import com.sun.javadoc.*; import java.io.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; /** * Generate the Serialized Form Information Page. @@ -64,76 +66,167 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter } /** - * Write the given package header. + * Get the given header. * - * @param packageName the package header to write. + * @param header the header to write + * @return the body content tree */ - public void writePackageHeader(String packageName) { - hr(4, "noshade"); - tableHeader(); - thAlign("center"); - font("+2"); - strongText("doclet.Package"); - print(' '); - strong(packageName); - tableFooter(); + public Content getHeader(String header) { + Content bodyTree = getBody(true, getWindowTitle(header)); + addTop(bodyTree); + addNavLinks(true, bodyTree); + Content h1Content = new StringContent(header); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.title, h1Content); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + bodyTree.addContent(div); + return bodyTree; } /** - * Write the serial UID info. + * Get the serialized form summaries header. * - * @param header the header that will show up before the UID. - * @param serialUID the serial UID to print. + * @return the serialized form summary header tree */ - public void writeSerialUIDInfo(String header, String serialUID) { - strong(header + " "); - println(serialUID); - p(); + public Content getSerializedSummariesHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; } /** - * Write the footer. + * Get the package serialized form header. + * + * @return the package serialized form header tree */ - public void writeFooter() { - p(); - hr(); - navLinks(false); - printBottom(); - printBodyHtmlEnd(); + public Content getPackageSerializedHeader() { + HtmlTree li = new HtmlTree(HtmlTag.LI); + li.addStyle(HtmlStyle.blockList); + return li; } + /** + * Get the given package header. + * + * @param packageName the package header to write + * @return a content tree for the package header + */ + public Content getPackageHeader(String packageName) { + Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, + packageLabel); + heading.addContent(getSpace()); + heading.addContent(packageName); + return heading; + } /** - * Write the serializable class heading. + * Get the serialized class header. * - * @param classDoc the class being processed. + * @return a content tree for the serialized class header */ - public void writeClassHeader(ClassDoc classDoc) { + public Content getClassSerializedHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * Get the serializable class heading. + * + * @param classDoc the class being processed + * @return a content tree for the class header + */ + public Content getClassHeader(ClassDoc classDoc) { String classLink = (classDoc.isPublic() || classDoc.isProtected())? getLink(new LinkInfoImpl(classDoc, - configuration.getClassName(classDoc))): + configuration.getClassName(classDoc))): classDoc.qualifiedName(); - p(); - anchor(classDoc.qualifiedName()); + Content li = HtmlTree.LI(HtmlStyle.blockList, getMarkerAnchor( + classDoc.qualifiedName())); String superClassLink = classDoc.superclassType() != null ? getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_SERIALIZED_FORM, - classDoc.superclassType())) : + classDoc.superclassType())) : null; //Print the heading. String className = superClassLink == null ? configuration.getText( - "doclet.Class_0_implements_serializable", classLink) : + "doclet.Class_0_implements_serializable", classLink) : configuration.getText( - "doclet.Class_0_extends_implements_serializable", classLink, - superClassLink); - tableHeader(); - thAlignColspan("left", 2); - font("+2"); - strong(className); - tableFooter(); - p(); + "doclet.Class_0_extends_implements_serializable", classLink, + superClassLink); + Content classNameContent = new RawHtml(className); + li.addContent(HtmlTree.HEADING(HtmlConstants.SERIALIZED_MEMBER_HEADING, + classNameContent)); + return li; + } + + /** + * Get the serial UID info header. + * + * @return a content tree for the serial uid info header + */ + public Content getSerialUIDInfoHeader() { + HtmlTree dl = new HtmlTree(HtmlTag.DL); + dl.addStyle(HtmlStyle.nameValue); + return dl; + } + + /** + * Adds the serial UID info. + * + * @param header the header that will show up before the UID. + * @param serialUID the serial UID to print. + * @param serialUidTree the serial UID content tree to which the serial UID + * content will be added + */ + public void addSerialUIDInfo(String header, String serialUID, + Content serialUidTree) { + Content headerContent = new StringContent(header); + serialUidTree.addContent(HtmlTree.DT(headerContent)); + Content serialContent = new StringContent(serialUID); + serialUidTree.addContent(HtmlTree.DD(serialContent)); + } + + /** + * Get the class serialize content header. + * + * @return a content tree for the class serialize content header + */ + public Content getClassContentHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * Get the serialized content tree section. + * + * @param serializedTreeContent the serialized content tree to be added + * @return a div content tree + */ + public Content getSerializedContent(Content serializedTreeContent) { + Content divContent = HtmlTree.DIV(HtmlStyle.serializedFormContainer, + serializedTreeContent); + return divContent; + } + + /** + * Add the footer. + * + * @param serializedTree the serialized tree to be added + */ + public void addFooter(Content serializedTree) { + addNavLinks(false, serializedTree); + addBottom(serializedTree); + } + + /** + * {@inheritDoc} + */ + public void printDocument(Content serializedTree) { + printHtmlDocument(null, true, serializedTree); } private void tableHeader() { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SingleIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SingleIndexWriter.java index fcb6ece5883..8360be22ac4 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SingleIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SingleIndexWriter.java @@ -25,9 +25,10 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.util.*; - import java.io.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; /** * Generate only one index file for all the Member Names with Indexing in @@ -36,6 +37,7 @@ import java.io.*; * * @see java.lang.Character * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class SingleIndexWriter extends AbstractIndexWriter { @@ -82,34 +84,35 @@ public class SingleIndexWriter extends AbstractIndexWriter { * Member Field, Method and Constructor Description. */ protected void generateIndexFile() throws IOException { - printHtmlHeader(configuration.getText("doclet.Window_Single_Index"), - null, true); - printTop(); - navLinks(true); - printLinksForIndexes(); - - hr(); - + String title = configuration.getText("doclet.Window_Single_Index"); + Content body = getBody(true, getWindowTitle(title)); + addTop(body); + addNavLinks(true, body); + HtmlTree divTree = new HtmlTree(HtmlTag.DIV); + divTree.addStyle(HtmlStyle.contentContainer); + addLinksForIndexes(divTree); for (int i = 0; i < indexbuilder.elements().length; i++) { Character unicode = (Character)((indexbuilder.elements())[i]); - generateContents(unicode, indexbuilder.getMemberList(unicode)); + addContents(unicode, indexbuilder.getMemberList(unicode), divTree); } - - printLinksForIndexes(); - navLinks(false); - - printBottom(); - printBodyHtmlEnd(); + addLinksForIndexes(divTree); + body.addContent(divTree); + addNavLinks(false, body); + addBottom(body); + printHtmlDocument(null, true, body); } /** - * Print Links for all the Index Files per unicode character. + * Add links for all the Index Files per unicode character. + * + * @param contentTree the content tree to which the links for indexes will be added */ - protected void printLinksForIndexes() { + protected void addLinksForIndexes(Content contentTree) { for (int i = 0; i < indexbuilder.elements().length; i++) { String unicode = (indexbuilder.elements())[i].toString(); - printHyperLink("#_" + unicode + "_", unicode); - print(' '); + contentTree.addContent( + getHyperLink("#_" + unicode + "_", new StringContent(unicode))); + contentTree.addContent(getSpace()); } } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java similarity index 56% rename from langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java rename to langtools/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java index 578160588f5..1c85f2b7a4c 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java @@ -23,14 +23,14 @@ * questions. */ -package com.sun.tools.doclets.internal.toolkit.util; +package com.sun.tools.doclets.formats.html; import java.io.*; -import java.util.*; import javax.tools.FileObject; - import com.sun.javadoc.*; import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * Converts Java Source Code to HTML. @@ -40,27 +40,28 @@ import com.sun.tools.doclets.internal.toolkit.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.4 */ public class SourceToHTMLConverter { - /** - * The background color. - */ - protected static final String BGCOLOR = "white"; - - /** - * The line number color. - */ - protected static final String LINE_NO_COLOR = "green"; - /** * The number of trailing blank lines at the end of the page. * This is inserted so that anchors at the bottom of small pages * can be reached. */ - protected static final int NUM_BLANK_LINES = 60; + private static final int NUM_BLANK_LINES = 60; + /** + * New line to be added to the documentation. + */ + private static final Content NEW_LINE = new RawHtml(DocletConstants.NL); + + /** + * Relative path from the documentation root to the file that is being + * generated. + */ + private static String relativePath = ""; /** * Source is converted to HTML using static methods below. @@ -69,11 +70,13 @@ public class SourceToHTMLConverter { /** * Convert the Classes in the given RootDoc to an HTML. + * * @param configuration the configuration. * @param rd the RootDoc to convert. * @param outputdir the name of the directory to output to. */ - public static void convertRoot(Configuration configuration, RootDoc rd, String outputdir) { + public static void convertRoot(ConfigurationImpl configuration, RootDoc rd, + String outputdir) { if (rd == null || outputdir == null) { return; } @@ -84,17 +87,19 @@ public class SourceToHTMLConverter { ClassDoc[] cds = rd.specifiedClasses(); for (int i = 0; i < cds.length; i++) { convertClass(configuration, cds[i], - getPackageOutputDir(outputdir, cds[i].containingPackage())); + getPackageOutputDir(outputdir, cds[i].containingPackage())); } } /** * Convert the Classes in the given Package to an HTML. + * * @param configuration the configuration. * @param pd the Package to convert. * @param outputdir the name of the directory to output to. */ - public static void convertPackage(Configuration configuration, PackageDoc pd, String outputdir) { + public static void convertPackage(ConfigurationImpl configuration, PackageDoc pd, + String outputdir) { if (pd == null || outputdir == null) { return; } @@ -107,8 +112,10 @@ public class SourceToHTMLConverter { /** * Return the directory write output to for the given package. + * * @param outputDir the directory to output to. * @param pd the Package to generate output for. + * @return the package output directory as a String. */ private static String getPackageOutputDir(String outputDir, PackageDoc pd) { return outputDir + File.separator + @@ -117,11 +124,13 @@ public class SourceToHTMLConverter { /** * Convert the given Class to an HTML. + * * @param configuration the configuration. * @param cd the class to convert. * @param outputdir the name of the directory to output to. */ - public static void convertClass(Configuration configuration, ClassDoc cd, String outputdir) { + public static void convertClass(ConfigurationImpl configuration, ClassDoc cd, + String outputdir) { if (cd == null || outputdir == null) { return; } @@ -145,19 +154,23 @@ public class SourceToHTMLConverter { LineNumberReader reader = new LineNumberReader(r); int lineno = 1; String line; - StringBuffer output = new StringBuffer(); + relativePath = DirectoryManager.getRelativePath(DocletConstants.SOURCE_OUTPUT_DIR_NAME) + + DirectoryManager.getRelativePath(cd.containingPackage()); + Content body = getHeader(); + Content pre = new HtmlTree(HtmlTag.PRE); try { while ((line = reader.readLine()) != null) { - output.append(formatLine(line, configuration.sourcetab, lineno)); + addLineNo(pre, lineno); + addLine(pre, line, configuration.sourcetab, lineno); lineno++; } } finally { reader.close(); } - output = addLineNumbers(output.toString()); - output.insert(0, getHeader(configuration)); - output.append(getFooter()); - writeToFile(output.toString(), outputdir, cd.name(), configuration); + addBlankLines(pre); + Content div = HtmlTree.DIV(HtmlStyle.sourceContainer, pre); + body.addContent(div); + writeToFile(body, outputdir, cd.name(), configuration); } catch (Exception e){ e.printStackTrace(); } @@ -165,135 +178,117 @@ public class SourceToHTMLConverter { /** * Write the output to the file. - * @param output the string to output. + * + * @param body the documentation content to be written to the file. * @param outputDir the directory to output to. * @param className the name of the class that I am converting to HTML. * @param configuration the Doclet configuration to pass notices to. */ - private static void writeToFile(String output, String outputDir, String className, Configuration configuration) throws IOException { + private static void writeToFile(Content body, String outputDir, + String className, ConfigurationImpl configuration) throws IOException { + Content htmlDocType = DocType.Transitional(); + Content head = new HtmlTree(HtmlTag.HEAD); + head.addContent(HtmlTree.TITLE(new StringContent( + configuration.getText("doclet.Window_Source_title")))); + head.addContent(getStyleSheetProperties(configuration)); + Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), + head, body); + Content htmlDocument = new HtmlDocument(htmlDocType, htmlTree); File dir = new File(outputDir); dir.mkdirs(); File newFile = new File(dir, className + ".html"); configuration.message.notice("doclet.Generating_0", newFile.getPath()); FileOutputStream fout = new FileOutputStream(newFile); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fout)); - bw.write(output); + bw.write(htmlDocument.toString()); bw.close(); fout.close(); } /** - * Given a String, add line numbers. - * @param s the text to add line numbers to. + * Returns a link to the stylesheet file. * - * @return the string buffer with the line numbering for each line. + * @param configuration the doclet configuration for the current run of javadoc + * @return an HtmlTree for the lINK tag which provides the stylesheet location */ - private static StringBuffer addLineNumbers(String s) { - StringBuffer sb = new StringBuffer(); - StringTokenizer st = new StringTokenizer(s, "\n", true); - int lineno = 1; - String current; - while(st.hasMoreTokens()){ - current = st.nextToken(); - sb.append(current.equals("\n") ? - getHTMLLineNo(lineno) + current : - getHTMLLineNo(lineno) + current + st.nextToken()); - lineno++; + public static HtmlTree getStyleSheetProperties(ConfigurationImpl configuration) { + String filename = configuration.stylesheetfile; + if (filename.length() > 0) { + File stylefile = new File(filename); + String parent = stylefile.getParent(); + filename = (parent == null)? + filename: + filename.substring(parent.length() + 1); + } else { + filename = "stylesheet.css"; } - return sb; + filename = relativePath + filename; + HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", filename, "Style"); + return link; } /** * Get the header. - * @param configuration the Doclet configuration - * @return the header to the output file + * + * @return the header content for the HTML file */ - protected static String getHeader(Configuration configuration) { - StringBuffer result = new StringBuffer("" + DocletConstants.NL); - result.append("" + DocletConstants.NL); - result.append("
    " + DocletConstants.NL);
    -        return result.toString();
    +    private static Content getHeader() {
    +        return new HtmlTree(HtmlTag.BODY);
         }
     
         /**
    -     * Get the footer
    -     * @return the footer to the output file
    -     */
    -    protected static String getFooter() {
    -        StringBuffer footer = new StringBuffer();
    -        for (int i = 0; i < NUM_BLANK_LINES; i++) {
    -            footer.append(DocletConstants.NL);
    -        }
    -        footer.append("
    " + DocletConstants.NL + "" + - DocletConstants.NL + "" + DocletConstants.NL); - return footer.toString(); - } - - /** - * Get the HTML for the lines. + * Add the line numbers for the source code. + * + * @param pre the content tree to which the line number will be added * @param lineno The line number - * @return the HTML code for the line */ - protected static String getHTMLLineNo(int lineno) { - StringBuffer result = new StringBuffer(""); + private static void addLineNo(Content pre, int lineno) { + HtmlTree span = new HtmlTree(HtmlTag.SPAN); + span.addStyle(HtmlStyle.sourceLineNo); if (lineno < 10) { - result.append("00" + ((new Integer(lineno)).toString())); + span.addContent("00" + Integer.toString(lineno)); } else if (lineno < 100) { - result.append("0" + ((new Integer(lineno)).toString())); + span.addContent("0" + Integer.toString(lineno)); } else { - result.append((new Integer(lineno)).toString()); + span.addContent(Integer.toString(lineno)); } - result.append(" "); - return result.toString(); + pre.addContent(span); } /** - * Format a given line of source.
    - * Note: In the future, we will add special colors for constructs in the - * language. + * Add a line from source to the HTML file that is generated. + * + * @param pre the content tree to which the line will be added. * @param line the string to format. * @param tabLength the number of spaces for each tab. * @param currentLineNo the current number. */ - protected static String formatLine(String line, int tabLength, int currentLineNo) { - if (line == null) { - return null; - } - StringBuffer lineBuffer = new StringBuffer(Util.escapeHtmlChars(line)); - //Insert an anchor for the line - lineBuffer.append(""); - lineBuffer.append(DocletConstants.NL); - Util.replaceTabs(tabLength, lineBuffer); - return lineBuffer.toString(); - } - - /** - * Given an array of Docs, add to the given HashMap the - * line numbers and anchors that should be inserted in the output at those lines. - * @param docs the array of Docs to add anchors for. - * @param hash the HashMap to add to. - */ - protected static void addToHash(Doc[] docs, HashMap hash) { - if(docs == null) { - return; - } - for(int i = 0; i < docs.length; i++) { - hash.put(docs[i].position().line(), getAnchor(docs[i])); + private static void addLine(Content pre, String line, int tabLength, + int currentLineNo) { + if (line != null) { + StringBuffer lineBuffer = new StringBuffer(Util.escapeHtmlChars(line)); + Util.replaceTabs(tabLength, lineBuffer); + pre.addContent(new RawHtml(lineBuffer.toString())); + Content anchor = HtmlTree.A_NAME("line." + Integer.toString(currentLineNo)); + pre.addContent(anchor); + pre.addContent(NEW_LINE); } } /** - * Given a Doc, return an anchor for it. - * @param d the Doc to check. - * @return an anchor of the form <a name="my_name"></a> + * Add trailing blank lines at the end of the page. + * + * @param pre the content tree to which the blank lines will be added. */ - protected static String getAnchor(Doc d) { - return " "; + private static void addBlankLines(Content pre) { + for (int i = 0; i < NUM_BLANK_LINES; i++) { + pre.addContent(NEW_LINE); + } } /** * Given a Doc, return an anchor name for it. + * * @param d the Doc to check. * @return the name of the anchor. */ diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SplitIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SplitIndexWriter.java index e539667821b..17788129bc3 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SplitIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SplitIndexWriter.java @@ -25,9 +25,10 @@ package com.sun.tools.doclets.formats.html; -import com.sun.tools.doclets.internal.toolkit.util.*; - import java.io.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; /** * Generate Separate Index Files for all the member names with Indexing in @@ -36,6 +37,7 @@ import java.io.*; * * @see java.lang.Character * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class SplitIndexWriter extends AbstractIndexWriter { @@ -109,56 +111,68 @@ public class SplitIndexWriter extends AbstractIndexWriter { * index. */ protected void generateIndexFile(Character unicode) throws IOException { - printHtmlHeader(configuration.getText("doclet.Window_Split_Index", - unicode.toString()), null, true); - printTop(); - navLinks(true); - printLinksForIndexes(); - - hr(); - - generateContents(unicode, indexbuilder.getMemberList(unicode)); - - navLinks(false); - printLinksForIndexes(); - - printBottom(); - printBodyHtmlEnd(); + String title = configuration.getText("doclet.Window_Split_Index", + unicode.toString()); + Content body = getBody(true, getWindowTitle(title)); + addTop(body); + addNavLinks(true, body); + HtmlTree divTree = new HtmlTree(HtmlTag.DIV); + divTree.addStyle(HtmlStyle.contentContainer); + addLinksForIndexes(divTree); + addContents(unicode, indexbuilder.getMemberList(unicode), divTree); + addLinksForIndexes(divTree); + body.addContent(divTree); + addNavLinks(false, body); + addBottom(body); + printHtmlDocument(null, true, body); } /** - * Print Links for all the Index Files per unicode character. + * Add links for all the Index Files per unicode character. + * + * @param contentTree the content tree to which the links for indexes will be added */ - protected void printLinksForIndexes() { - for (int i = 0; i < indexbuilder.elements().length; i++) { + protected void addLinksForIndexes(Content contentTree) { + Object[] unicodeChars = indexbuilder.elements(); + for (int i = 0; i < unicodeChars.length; i++) { int j = i + 1; - printHyperLink("index-" + j + ".html", - indexbuilder.elements()[i].toString()); - print(' '); + contentTree.addContent(getHyperLink("index-" + j + ".html", + new StringContent(unicodeChars[i].toString()))); + contentTree.addContent(getSpace()); } } /** - * Print the previous unicode character index link. + * Get link to the previous unicode character. + * + * @return a content tree for the link */ - protected void navLinkPrevious() { + public Content getNavLinkPrevious() { + Content prevletterLabel = getResource("doclet.Prev_Letter"); if (prev == -1) { - printText("doclet.Prev_Letter"); - } else { - printHyperLink("index-" + prev + ".html", "", - configuration.getText("doclet.Prev_Letter"), true); + return HtmlTree.LI(prevletterLabel); + } + else { + Content prevLink = getHyperLink("index-" + prev + ".html", "", + prevletterLabel); + return HtmlTree.LI(prevLink); } } /** - * Print the next unicode character index link. + * Get link to the next unicode character. + * + * @return a content tree for the link */ - protected void navLinkNext() { + public Content getNavLinkNext() { + Content nextletterLabel = getResource("doclet.Next_Letter"); if (next == -1) { - printText("doclet.Next_Letter"); - } else { - printHyperLink("index-" + next + ".html","", - configuration.getText("doclet.Next_Letter"), true); + return HtmlTree.LI(nextletterLabel); + } + else { + Content nextLink = getHyperLink("index-" + next + ".html","", + nextletterLabel); + return HtmlTree.LI(nextLink); } } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/StylesheetWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/StylesheetWriter.java deleted file mode 100644 index 3363be5f8f7..00000000000 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/StylesheetWriter.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.doclets.formats.html; - -import com.sun.tools.doclets.internal.toolkit.util.*; - -import java.io.*; - -/** - * Writes the style sheet for the doclet output. - * - * @author Atul M Dambalkar - * @author Bhavesh Patel (Modified) - */ -public class StylesheetWriter extends HtmlDocletWriter { - - /** - * Constructor. - */ - public StylesheetWriter(ConfigurationImpl configuration, - String filename) throws IOException { - super(configuration, filename); - } - - /** - * Generate the style file contents. - * @throws DocletAbortException - */ - public static void generate(ConfigurationImpl configuration) { - StylesheetWriter stylegen; - String filename = ""; - try { - filename = "stylesheet.css"; - stylegen = new StylesheetWriter(configuration, filename); - stylegen.generateStyleFile(); - stylegen.close(); - } catch (IOException exc) { - configuration.standardmessage.error( - "doclet.exception_encountered", - exc.toString(), filename); - throw new DocletAbortException(); - } - } - - /** - * Generate the style file contents. - */ - protected void generateStyleFile() { - print("/* "); printText("doclet.Style_line_1"); println(" */"); - println(""); - - print("/* "); printText("doclet.Style_line_2"); println(" */"); - println(""); - - print("/* "); printText("doclet.Style_line_3"); println(" */"); - println("body { background-color: #FFFFFF; color:#000000 }"); - println(""); - - print("/* "); printText("doclet.Style_Headings"); println(" */"); - println("h1 { font-size: 145% }"); - println(""); - - print("/* "); printText("doclet.Style_line_4"); println(" */"); - print(".TableHeadingColor { background: #CCCCFF; color:#000000 }"); - print(" /* "); printText("doclet.Style_line_5"); println(" */"); - print(".TableSubHeadingColor { background: #EEEEFF; color:#000000 }"); - print(" /* "); printText("doclet.Style_line_6"); println(" */"); - print(".TableRowColor { background: #FFFFFF; color:#000000 }"); - print(" /* "); printText("doclet.Style_line_7"); println(" */"); - println(""); - - print("/* "); printText("doclet.Style_line_8"); println(" */"); - println(".FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 }"); - println(".FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 }"); - println(".FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 }"); - println(""); - - // Removed doclet.Style_line_9 as no longer needed - - print("/* "); printText("doclet.Style_line_10"); println(" */"); - print(".NavBarCell1 { background-color:#EEEEFF; color:#000000}"); - print(" /* "); printText("doclet.Style_line_6"); println(" */"); - print(".NavBarCell1Rev { background-color:#00008B; color:#FFFFFF}"); - print(" /* "); printText("doclet.Style_line_11"); println(" */"); - - print(".NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;"); - println("color:#000000;}"); - print(".NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;"); - println("color:#FFFFFF;}"); - println(""); - - print(".NavBarCell2 { font-family: Arial, Helvetica, sans-serif; "); - println("background-color:#FFFFFF; color:#000000}"); - print(".NavBarCell3 { font-family: Arial, Helvetica, sans-serif; "); - println("background-color:#FFFFFF; color:#000000}"); - - print("/* "); printText("doclet.Style_line_12"); println(" */"); - print(".TableCaption { background: #CCCCFF; color:#000000; text-align: left; font-size: 150%; font-weight: bold; border-left: 2px ridge; border-right: 2px ridge; border-top: 2px ridge; padding-left: 5px; }"); - print(" /* "); printText("doclet.Style_line_5"); println(" */"); - print(".TableSubCaption { background: #EEEEFF; color:#000000; text-align: left; font-weight: bold; border-left: 2px ridge; border-right: 2px ridge; border-top: 2px ridge; padding-left: 5px; }"); - print(" /* "); printText("doclet.Style_line_6"); println(" */"); - print(".TableHeader { text-align: center; font-size: 80%; font-weight: bold; }"); - println(""); - - } - -} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java index ae5a8e8db37..33e2fdc54f7 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java @@ -25,10 +25,11 @@ package com.sun.tools.doclets.formats.html; -import com.sun.javadoc.*; -import com.sun.tools.doclets.internal.toolkit.util.*; - import java.io.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; /** * This abstract class exists to provide functionality needed in the @@ -71,13 +72,31 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { tdEnd(); } - public void printSummaryHeader(AbstractMemberWriter mw, ClassDoc cd) { - mw.printSummaryAnchor(cd); - mw.printTableSummary(); - tableCaptionStart(); - mw.printSummaryLabel(); - tableCaptionEnd(); - mw.printSummaryTableHeader(cd); + /** + * Add the summary header. + * + * @param mw the writer for the member being documented + * @param cd the classdoc to be documented + * @param memberTree the content tree to which the summary header will be added + */ + public void addSummaryHeader(AbstractMemberWriter mw, ClassDoc cd, + Content memberTree) { + mw.addSummaryAnchor(cd, memberTree); + mw.addSummaryLabel(memberTree); + } + + /** + * Get the summary table. + * + * @param mw the writer for the member being documented + * @param cd the classdoc to be documented + * @return the content tree for the summary table + */ + public Content getSummaryTableTree(AbstractMemberWriter mw, ClassDoc cd) { + Content table = HtmlTree.TABLE(HtmlStyle.overviewSummary, 0, 3, 0, + mw.getTableSummary(), getTableCaption(mw.getCaption())); + table.addContent(getSummaryTableHeader(mw.getSummaryTableHeader(cd), "col")); + return table; } public void printTableHeadingBackground(String str) { @@ -88,15 +107,17 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { tableEnd(); } - public void printInheritedSummaryHeader(AbstractMemberWriter mw, ClassDoc cd) { - mw.printInheritedSummaryAnchor(cd); - tableIndexSummary(); - tableInheritedHeaderStart("#EEEEFF"); - mw.printInheritedSummaryLabel(cd); - tableInheritedHeaderEnd(); - trBgcolorStyle("white", "TableRowColor"); - summaryRow(0); - code(); + /** + * Add the inherited summary header. + * + * @param mw the writer for the member being documented + * @param cd the classdoc to be documented + * @param inheritedTree the content tree to which the inherited summary header will be added + */ + public void addInheritedSummaryHeader(AbstractMemberWriter mw, ClassDoc cd, + Content inheritedTree) { + mw.addInheritedSummaryAnchor(cd, inheritedTree); + mw.addInheritedSummaryLabel(cd, inheritedTree); } public void printSummaryFooter(AbstractMemberWriter mw, ClassDoc cd) { @@ -112,8 +133,14 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { space(); } - protected void printIndexComment(Doc member) { - printIndexComment(member, member.firstSentenceTags()); + /** + * Add the index comment. + * + * @param member the member being documented + * @param contentTree the content tree to which the comment will be added + */ + protected void addIndexComment(Doc member, Content contentTree) { + addIndexComment(member, member.firstSentenceTags(), contentTree); } protected void printIndexComment(Doc member, Tag[] firstSentenceTags) { @@ -134,17 +161,60 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { printSummaryComment(member, firstSentenceTags); } - public void printSummaryLinkType(AbstractMemberWriter mw, - ProgramElementDoc member) { - trBgcolorStyle("white", "TableRowColor"); - mw.printSummaryType(member); - summaryRow(0); - code(); + /** + * Add the index comment. + * + * @param member the member being documented + * @param firstSentenceTags the first sentence tags for the member to be documented + * @param tdSummary the content tree to which the comment will be added + */ + protected void addIndexComment(Doc member, Tag[] firstSentenceTags, + Content tdSummary) { + Tag[] deprs = member.tags("deprecated"); + Content div; + if (Util.isDeprecated((ProgramElementDoc) member)) { + Content strong = HtmlTree.STRONG(deprecatedPhrase); + div = HtmlTree.DIV(HtmlStyle.block, strong); + div.addContent(getSpace()); + if (deprs.length > 0) { + addInlineDeprecatedComment(member, deprs[0], div); + } + tdSummary.addContent(div); + return; + } else { + ClassDoc cd = ((ProgramElementDoc)member).containingClass(); + if (cd != null && Util.isDeprecated(cd)) { + Content strong = HtmlTree.STRONG(deprecatedPhrase); + div = HtmlTree.DIV(HtmlStyle.block, strong); + div.addContent(getSpace()); + tdSummary.addContent(div); + } + } + addSummaryComment(member, firstSentenceTags, tdSummary); } - public void printSummaryLinkComment(AbstractMemberWriter mw, - ProgramElementDoc member) { - printSummaryLinkComment(mw, member, member.firstSentenceTags()); + /** + * Add the summary type for the member. + * + * @param mw the writer for the member being documented + * @param member the member to be documented + * @param tdSummaryType the content tree to which the type will be added + */ + public void addSummaryType(AbstractMemberWriter mw, ProgramElementDoc member, + Content tdSummaryType) { + mw.addSummaryType(member, tdSummaryType); + } + + /** + * Add the summary link for the member. + * + * @param mw the writer for the member being documented + * @param member the member to be documented + * @param contentTree the content tree to which the link will be added + */ + public void addSummaryLinkComment(AbstractMemberWriter mw, + ProgramElementDoc member, Content contentTree) { + addSummaryLinkComment(mw, member, member.firstSentenceTags(), contentTree); } public void printSummaryLinkComment(AbstractMemberWriter mw, @@ -159,12 +229,34 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { trEnd(); } - public void printInheritedSummaryMember(AbstractMemberWriter mw, ClassDoc cd, - ProgramElementDoc member, boolean isFirst) { + /** + * Add the summary link comment. + * + * @param mw the writer for the member being documented + * @param member the member being documented + * @param firstSentenceTags the first sentence tags for the member to be documented + * @param tdSummary the content tree to which the comment will be added + */ + public void addSummaryLinkComment(AbstractMemberWriter mw, + ProgramElementDoc member, Tag[] firstSentenceTags, Content tdSummary) { + addIndexComment(member, firstSentenceTags, tdSummary); + } + + /** + * Add the inherited member summary. + * + * @param mw the writer for the member being documented + * @param cd the class being documented + * @param member the member being documented + * @param isFirst true if its the first link being documented + * @param linksTree the content tree to which the summary will be added + */ + public void addInheritedMemberSummary(AbstractMemberWriter mw, ClassDoc cd, + ProgramElementDoc member, boolean isFirst, Content linksTree) { if (! isFirst) { - mw.print(", "); + linksTree.addContent(", "); } - mw.writeInheritedSummaryLink(cd, member); + mw.addInheritedSummaryLink(cd, member, linksTree); } public void printMemberHeader() { @@ -174,4 +266,67 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { public void printMemberFooter() { } + /** + * Get the document content header tree + * + * @return a content tree the document content header + */ + public Content getContentHeader() { + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.contentContainer); + return div; + } + + /** + * Get the member header tree + * + * @return a content tree the member header + */ + public Content getMemberTreeHeader() { + HtmlTree li = new HtmlTree(HtmlTag.LI); + li.addStyle(HtmlStyle.blockList); + return li; + } + + /** + * Get the member tree + * + * @param contentTree the tree used to generate the complete member tree + * @return a content tree for the member + */ + public Content getMemberTree(Content contentTree) { + Content ul = HtmlTree.UL(HtmlStyle.blockList, contentTree); + return ul; + } + + /** + * Get the member summary tree + * + * @param contentTree the tree used to generate the member summary tree + * @return a content tree for the member summary + */ + public Content getMemberSummaryTree(Content contentTree) { + return getMemberTree(HtmlStyle.summary, contentTree); + } + + /** + * Get the member details tree + * + * @param contentTree the tree used to generate the member details tree + * @return a content tree for the member details + */ + public Content getMemberDetailsTree(Content contentTree) { + return getMemberTree(HtmlStyle.details, contentTree); + } + + /** + * Get the member tree + * + * @param style the style class to be added to the content tree + * @param contentTree the tree used to generate the complete member tree + */ + public Content getMemberTree(HtmlStyle style, Content contentTree) { + Content div = HtmlTree.DIV(style, getMemberTree(contentTree)); + return div; + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TagletWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TagletWriterImpl.java index 2f7c0071f94..b3570d58190 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TagletWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TagletWriterImpl.java @@ -70,9 +70,9 @@ public class TagletWriterImpl extends TagletWriter { Tag[] deprs = doc.tags("deprecated"); if (doc instanceof ClassDoc) { if (Util.isDeprecated((ProgramElementDoc) doc)) { - output.append("" + + output.append("" + ConfigurationImpl.getInstance(). - getText("doclet.Deprecated") + " "); + getText("doclet.Deprecated") + " "); if (deprs.length > 0) { Tag[] commentTags = deprs[0].inlineTags(); if (commentTags.length > 0) { @@ -82,30 +82,24 @@ public class TagletWriterImpl extends TagletWriter { ); } } - output.append("

    "); } } else { MemberDoc member = (MemberDoc) doc; if (Util.isDeprecated((ProgramElementDoc) doc)) { - output.append("

    " + + output.append("" + ConfigurationImpl.getInstance(). - getText("doclet.Deprecated") + " "); + getText("doclet.Deprecated") + " "); if (deprs.length > 0) { - output.append(""); + output.append(""); output.append(commentTagsToOutput(null, doc, deprs[0].inlineTags(), false).toString()); - output.append(""); + output.append(""); } - if (member instanceof ExecutableMemberDoc) { - output.append(DocletConstants.NL + "

    " + - DocletConstants.NL); - } - output.append("

    "); } else { if (Util.isDeprecated(member.containingClass())) { - output.append("
    " + + output.append("" + ConfigurationImpl.getInstance(). - getText("doclet.Deprecated") + " 
    "); + getText("doclet.Deprecated") + " "); } } } @@ -124,8 +118,8 @@ public class TagletWriterImpl extends TagletWriter { */ public TagletOutput getParamHeader(String header) { StringBuffer result = new StringBuffer(); - result.append("
    "); - result.append("" + header + "
    "); + result.append("
    "); + result.append("" + header + "
    "); return new TagletOutputImpl(result.toString()); } @@ -133,8 +127,8 @@ public class TagletWriterImpl extends TagletWriter { * {@inheritDoc} */ public TagletOutput paramTagOutput(ParamTag paramTag, String paramName) { - TagletOutput result = new TagletOutputImpl("
    " + paramName + "" - + " - " + htmlWriter.commentTagsToString(paramTag, null, paramTag.inlineTags(), false) + "
    "); + TagletOutput result = new TagletOutputImpl("
    " + paramName + "" + + " - " + htmlWriter.commentTagsToString(paramTag, null, paramTag.inlineTags(), false) + "
    "); return result; } @@ -142,11 +136,11 @@ public class TagletWriterImpl extends TagletWriter { * {@inheritDoc} */ public TagletOutput returnTagOutput(Tag returnTag) { - TagletOutput result = new TagletOutputImpl(DocletConstants.NL + "
    " + - "" + htmlWriter.configuration.getText("doclet.Returns") + - "" + "
    " + "
    " + + TagletOutput result = new TagletOutputImpl(DocletConstants.NL + "
    " + + "" + htmlWriter.configuration.getText("doclet.Returns") + + "" + "
    " + "
    " + htmlWriter.commentTagsToString(returnTag, null, returnTag.inlineTags(), - false) + "
    "); + false) + ""); return result; } @@ -168,7 +162,7 @@ public class TagletWriterImpl extends TagletWriter { htmlWriter instanceof ClassWriterImpl) { //Automatically add link to constant values page for constant fields. result = addSeeHeader(result); - result += htmlWriter.getHyperLink(htmlWriter.relativePath + + result += htmlWriter.getHyperLinkString(htmlWriter.relativePath + ConfigurationImpl.CONSTANTS_FILE_NAME + "#" + ((ClassWriterImpl) htmlWriter).getClassDoc().qualifiedName() + "." + ((FieldDoc) holder).name(), @@ -179,18 +173,19 @@ public class TagletWriterImpl extends TagletWriter { if ((SerializedFormBuilder.serialInclude(holder) && SerializedFormBuilder.serialInclude(((ClassDoc)holder).containingPackage()))) { result = addSeeHeader(result); - result += htmlWriter.getHyperLink(htmlWriter.relativePath + "serialized-form.html", + result += htmlWriter.getHyperLinkString(htmlWriter.relativePath + "serialized-form.html", ((ClassDoc)holder).qualifiedName(), htmlWriter.configuration.getText("doclet.Serialized_Form"), false); } } - return result.equals("") ? null : new TagletOutputImpl(result + ""); + return result.equals("") ? null : new TagletOutputImpl(result + ""); } private String addSeeHeader(String result) { if (result != null && result.length() > 0) { return result + ", " + DocletConstants.NL; } else { - return "
    " + htmlWriter.configuration().getText("doclet.See_Also") + "
    "; + return "
    " + + htmlWriter.configuration().getText("doclet.See_Also") + "
    "; } } @@ -198,15 +193,15 @@ public class TagletWriterImpl extends TagletWriter { * {@inheritDoc} */ public TagletOutput simpleTagOutput(Tag[] simpleTags, String header) { - String result = "
    " + header + "
    " + DocletConstants.NL + - "
    "; + String result = "
    " + header + "
    " + DocletConstants.NL + + "
    "; for (int i = 0; i < simpleTags.length; i++) { if (i > 0) { result += ", "; } result += htmlWriter.commentTagsToString(simpleTags[i], null, simpleTags[i].inlineTags(), false); } - result += "
    " + DocletConstants.NL; + result += "" + DocletConstants.NL; return new TagletOutputImpl(result); } @@ -214,24 +209,24 @@ public class TagletWriterImpl extends TagletWriter { * {@inheritDoc} */ public TagletOutput simpleTagOutput(Tag simpleTag, String header) { - return new TagletOutputImpl("
    " + header + "
    " + "
    " + return new TagletOutputImpl("
    " + header + "
    " + "
    " + htmlWriter.commentTagsToString(simpleTag, null, simpleTag.inlineTags(), false) - + "
    " + DocletConstants.NL); + + "" + DocletConstants.NL); } /** * {@inheritDoc} */ public TagletOutput getThrowsHeader() { - return new TagletOutputImpl(DocletConstants.NL + "
    " + "" + - htmlWriter.configuration().getText("doclet.Throws") + "
    "); + return new TagletOutputImpl(DocletConstants.NL + "
    " + "" + + htmlWriter.configuration().getText("doclet.Throws") + "
    "); } /** * {@inheritDoc} */ public TagletOutput throwsTagOutput(ThrowsTag throwsTag) { - String result = DocletConstants.NL + "
    "; + String result = DocletConstants.NL + "
    "; result += throwsTag.exceptionType() == null ? htmlWriter.codeText(throwsTag.exceptionName()) : htmlWriter.codeText( @@ -243,7 +238,7 @@ public class TagletWriterImpl extends TagletWriter { if (text != null && text.toString().length() > 0) { result += " - " + text; } - result += "
    "; + result += ""; return new TagletOutputImpl(result); } @@ -251,9 +246,9 @@ public class TagletWriterImpl extends TagletWriter { * {@inheritDoc} */ public TagletOutput throwsTagOutput(Type throwsType) { - return new TagletOutputImpl(DocletConstants.NL + "
    " + + return new TagletOutputImpl(DocletConstants.NL + "
    " + htmlWriter.codeText(htmlWriter.getLink( - new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, throwsType))) + "
    "); + new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, throwsType))) + ""); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java index 5dc678da549..3f1553e2c9a 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TreeWriter.java @@ -29,6 +29,8 @@ import java.io.*; import com.sun.javadoc.*; import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; /** * Generate Class Hierarchy page for all the Classes in this run. Use @@ -37,6 +39,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * current or the destination directory. * * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class TreeWriter extends AbstractTreeWriter { @@ -90,86 +93,70 @@ public class TreeWriter extends AbstractTreeWriter { } /** - * Print the interface hierarchy and class hierarchy in the file. + * Generate the interface hierarchy and class hierarchy. */ public void generateTreeFile() throws IOException { - printHtmlHeader(configuration.getText("doclet.Window_Class_Hierarchy"), - null, true); - - printTreeHeader(); - - printPageHeading(); - - printPackageTreeLinks(); - - generateTree(classtree.baseclasses(), "doclet.Class_Hierarchy"); - generateTree(classtree.baseinterfaces(), "doclet.Interface_Hierarchy"); - generateTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy"); - generateTree(classtree.baseEnums(), "doclet.Enum_Hierarchy"); - - printTreeFooter(); + Content body = getTreeHeader(); + Content headContent = getResource("doclet.Hierarchy_For_All_Packages"); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, false, + HtmlStyle.title, headContent); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + addPackageTreeLinks(div); + body.addContent(div); + HtmlTree divTree = new HtmlTree(HtmlTag.DIV); + divTree.addStyle(HtmlStyle.contentContainer); + addTree(classtree.baseclasses(), "doclet.Class_Hierarchy", divTree); + addTree(classtree.baseinterfaces(), "doclet.Interface_Hierarchy", divTree); + addTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy", divTree); + addTree(classtree.baseEnums(), "doclet.Enum_Hierarchy", divTree); + body.addContent(divTree); + addNavLinks(false, body); + addBottom(body); + printHtmlDocument(null, true, body); } /** - * Generate the links to all the package tree files. + * Add the links to all the package tree files. + * + * @param contentTree the content tree to which the links will be added */ - protected void printPackageTreeLinks() { + protected void addPackageTreeLinks(Content contentTree) { //Do nothing if only unnamed package is used if (packages.length == 1 && packages[0].name().length() == 0) { return; } if (!classesonly) { - dl(); - dt(); - strongText("doclet.Package_Hierarchies"); - dtEnd(); - dd(); + Content span = HtmlTree.SPAN(HtmlStyle.strong, + getResource("doclet.Package_Hierarchies")); + contentTree.addContent(span); + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.horizontal); for (int i = 0; i < packages.length; i++) { if (packages[i].name().length() == 0) { continue; } - String filename = pathString(packages[i], "package-tree.html"); - printHyperLink(filename, "", packages[i].name()); + String link = pathString(packages[i], "package-tree.html"); + Content li = HtmlTree.LI(getHyperLink( + link, "", new StringContent(packages[i].name()))); if (i < packages.length - 1) { - print(", "); + li.addContent(", "); } + ul.addContent(li); } - ddEnd(); - dlEnd(); - hr(); + contentTree.addContent(ul); } } /** - * Print the top text (from the -top option) and - * navigation bar at the top of page. + * Get the tree header. + * + * @return a content tree for the tree header */ - protected void printTreeHeader() { - printTop(); - navLinks(true); - hr(); - } - - /** - * Print the navigation bar and bottom text (from the -bottom option) - * at the bottom of page. - */ - protected void printTreeFooter() { - hr(); - navLinks(false); - printBottom(); - printBodyHtmlEnd(); - } - - /** - * Print the page title "Hierarchy For All Packages" at the top of the tree - * page. - */ - protected void printPageHeading() { - center(); - h2(); - printText("doclet.Hierarchy_For_All_Packages"); - h2End(); - centerEnd(); + protected Content getTreeHeader() { + String title = configuration.getText("doclet.Window_Class_Hierarchy"); + Content bodyTree = getBody(true, getWindowTitle(title)); + addTop(bodyTree); + addNavLinks(true, bodyTree); + return bodyTree; } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/Comment.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/Comment.java new file mode 100644 index 00000000000..92ca93d44c8 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/Comment.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.formats.html.markup; + +import com.sun.tools.doclets.internal.toolkit.Content; +import com.sun.tools.doclets.internal.toolkit.util.*; + +/** + * Class for generating a comment for HTML pages of javadoc output. + * + * @author Bhavesh Patel + */ +public class Comment extends Content{ + + private String commentText; + + /** + * Constructor to construct a Comment object. + * + * @param comment comment text for the comment + */ + public Comment(String comment) { + commentText = nullCheck(comment); + } + + /** + * This method is not supported by the class. + * + * @param content content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(Content content) { + throw new DocletAbortException(); + } + + /** + * This method is not supported by the class. + * + * @param stringContent string content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(String stringContent) { + throw new DocletAbortException(); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return commentText.isEmpty(); + } + + /** + * {@inheritDoc} + */ + public void write(StringBuilder contentBuilder) { + if (!endsWithNewLine(contentBuilder)) + contentBuilder.append("\n"); + contentBuilder.append("\n"); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/DocType.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/DocType.java new file mode 100644 index 00000000000..dc1806c5bf1 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/DocType.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.formats.html.markup; + +import com.sun.tools.doclets.internal.toolkit.Content; +import com.sun.tools.doclets.internal.toolkit.util.*; + +/** + * Class for generating document type for HTML pages of javadoc output. + * + * @author Bhavesh Patel + */ +public class DocType extends Content{ + + private String docType; + + private static DocType transitional; + + private static DocType frameset; + + /** + * Constructor to construct a DocType object. + * + * @param type the doctype to be added + */ + private DocType(String type, String dtd) { + docType = "\n"; + } + + /** + * Construct and return a HTML 4.01 transitional DocType content + * + * @return a content tree for transitional DocType + */ + public static DocType Transitional() { + if (transitional == null) + transitional = new DocType("Transitional", "http://www.w3.org/TR/html4/loose.dtd"); + return transitional; + } + + /** + * Construct and return a HTML 4.01 frameset DocType content + * + * @return a content tree for frameset DocType + */ + public static DocType Frameset() { + if (frameset == null) + frameset = new DocType("Frameset", "http://www.w3.org/TR/html4/frameset.dtd"); + return frameset; + } + + /** + * This method is not supported by the class. + * + * @param content content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(Content content) { + throw new DocletAbortException(); + } + + /** + * This method is not supported by the class. + * + * @param stringContent string content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(String stringContent) { + throw new DocletAbortException(); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return (docType.length() == 0); + } + + /** + * {@inheritDoc} + */ + public void write(StringBuilder contentBuilder) { + contentBuilder.append(docType); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlAttr.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlAttr.java new file mode 100644 index 00000000000..96895531dd6 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlAttr.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.formats.html.markup; + +/** + * Enum representing HTML tag attributes. + * + * @author Bhavesh Patel + */ +public enum HtmlAttr { + ALT, + BORDER, + CELLPADDING, + CELLSPACING, + CHARSET, + CLASS, + CLEAR, + COLS, + CONTENT, + HREF, + HTTP_EQUIV("http-equiv"), + ID, + LANG, + NAME, + ONLOAD, + REL, + ROWS, + SCOPE, + SCROLLING, + SRC, + SUMMARY, + TARGET, + TITLE, + TYPE, + WIDTH; + + private final String value; + + HtmlAttr() { + this.value = name().toLowerCase(); + } + + HtmlAttr(String name) { + this.value = name; + } + + public String toString() { + return value; + } +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java new file mode 100644 index 00000000000..c85927e0b67 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.formats.html.markup; + +import com.sun.tools.doclets.internal.toolkit.Content; + +/** + * Stores constants for Html Doclet. + * + * @author Bhavesh Patel + */ +public class HtmlConstants { + + /** + * Marker to identify start of top navigation bar. + */ + public static final Content START_OF_TOP_NAVBAR = + new Comment("========= START OF TOP NAVBAR ======="); + + /** + * Marker to identify start of bottom navigation bar. + */ + public static final Content START_OF_BOTTOM_NAVBAR = + new Comment("======= START OF BOTTOM NAVBAR ======"); + + /** + * Marker to identify end of top navigation bar. + */ + public static final Content END_OF_TOP_NAVBAR = + new Comment("========= END OF TOP NAVBAR ========="); + + /** + * Marker to identify end of bottom navigation bar. + */ + public static final Content END_OF_BOTTOM_NAVBAR = + new Comment("======== END OF BOTTOM NAVBAR ======="); + + /** + * Marker to identify start of class data. + */ + public static final Content START_OF_CLASS_DATA = + new Comment("======== START OF CLASS DATA ========"); + + /** + * Marker to identify end of class data. + */ + public static final Content END_OF_CLASS_DATA = + new Comment("========= END OF CLASS DATA ========="); + + /** + * Marker to identify start of nested class summary. + */ + public static final Content START_OF_NESTED_CLASS_SUMMARY = + new Comment("======== NESTED CLASS SUMMARY ========"); + + /** + * Marker to identify start of annotation type optional member summary. + */ + public static final Content START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY = + new Comment("=========== ANNOTATION TYPE OPTIONAL MEMBER SUMMARY ==========="); + + /** + * Marker to identify start of annotation type required member summary. + */ + public static final Content START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY = + new Comment("=========== ANNOTATION TYPE REQUIRED MEMBER SUMMARY ==========="); + + /** + * Marker to identify start of constructor summary. + */ + public static final Content START_OF_CONSTRUCTOR_SUMMARY = + new Comment("======== CONSTRUCTOR SUMMARY ========"); + + /** + * Marker to identify start of enum constants summary. + */ + public static final Content START_OF_ENUM_CONSTANT_SUMMARY = + new Comment("=========== ENUM CONSTANT SUMMARY ==========="); + + /** + * Marker to identify start of field summary. + */ + public static final Content START_OF_FIELD_SUMMARY = + new Comment("=========== FIELD SUMMARY ==========="); + + /** + * Marker to identify start of method summary. + */ + public static final Content START_OF_METHOD_SUMMARY = + new Comment("========== METHOD SUMMARY ==========="); + + /** + * Marker to identify start of annotation type details. + */ + public static final Content START_OF_ANNOTATION_TYPE_DETAILS = + new Comment("============ ANNOTATION TYPE MEMBER DETAIL ==========="); + + /** + * Marker to identify start of method details. + */ + public static final Content START_OF_METHOD_DETAILS = + new Comment("============ METHOD DETAIL =========="); + + /** + * Marker to identify start of field details. + */ + public static final Content START_OF_FIELD_DETAILS = + new Comment("============ FIELD DETAIL ==========="); + + /** + * Marker to identify start of constructor details. + */ + public static final Content START_OF_CONSTRUCTOR_DETAILS = + new Comment("========= CONSTRUCTOR DETAIL ========"); + + /** + * Marker to identify start of enum constants details. + */ + public static final Content START_OF_ENUM_CONSTANT_DETAILS = + new Comment("============ ENUM CONSTANT DETAIL ==========="); + + /** + * Html tag for the page title heading. + */ + public static final HtmlTag TITLE_HEADING = HtmlTag.H1; + + /** + * Html tag for the class page title heading. + */ + public static final HtmlTag CLASS_PAGE_HEADING = HtmlTag.H2; + + /** + * Html tag for the content heading. + */ + public static final HtmlTag CONTENT_HEADING = HtmlTag.H2; + + /** + * Html tag for the package name heading. + */ + public static final HtmlTag PACKAGE_HEADING = HtmlTag.H2; + + /** + * Html tag for the member summary heading. + */ + public static final HtmlTag SUMMARY_HEADING = HtmlTag.H3; + + /** + * Html tag for the inherited member summary heading. + */ + public static final HtmlTag INHERITED_SUMMARY_HEADING = HtmlTag.H3; + + /** + * Html tag for the member details heading. + */ + public static final HtmlTag DETAILS_HEADING = HtmlTag.H3; + + /** + * Html tag for the serialized member heading. + */ + public static final HtmlTag SERIALIZED_MEMBER_HEADING = HtmlTag.H3; + + /** + * Html tag for the member heading. + */ + public static final HtmlTag MEMBER_HEADING = HtmlTag.H4; +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java index 7079a987f96..457508b1dc9 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java @@ -87,7 +87,7 @@ public abstract class HtmlDocWriter extends HtmlWriter { */ public void printHyperLink(String link, String where, String label, boolean strong) { - print(getHyperLink(link, where, label, strong, "", "", "")); + print(getHyperLinkString(link, where, label, strong, "", "", "")); } /** @@ -115,7 +115,7 @@ public abstract class HtmlDocWriter extends HtmlWriter { public void printHyperLink(String link, String where, String label, boolean strong, String stylename) { - print(getHyperLink(link, where, label, strong, stylename, "", "")); + print(getHyperLinkString(link, where, label, strong, stylename, "", "")); } /** @@ -128,9 +128,9 @@ public abstract class HtmlDocWriter extends HtmlWriter { * @param strong Boolean that sets label to strong. * @return String Hyper Link. */ - public String getHyperLink(String link, String where, + public String getHyperLinkString(String link, String where, String label, boolean strong) { - return getHyperLink(link, where, label, strong, "", "", ""); + return getHyperLinkString(link, where, label, strong, "", "", ""); } /** @@ -144,10 +144,24 @@ public abstract class HtmlDocWriter extends HtmlWriter { * @param stylename String style of text defined in style sheet. * @return String Hyper Link. */ - public String getHyperLink(String link, String where, + public String getHyperLinkString(String link, String where, String label, boolean strong, String stylename) { - return getHyperLink(link, where, label, strong, stylename, "", ""); + return getHyperLinkString(link, where, label, strong, stylename, "", ""); + } + + /** + * Get Html Hyper Link string. + * + * @param link String name of the file. + * @param where Position of the link in the file. Character '#' is not + * needed. + * @param label Tag for the link. + * @return a content tree for the hyper link + */ + public Content getHyperLink(String link, String where, + Content label) { + return getHyperLink(link, where, label, "", ""); } /** @@ -163,11 +177,11 @@ public abstract class HtmlDocWriter extends HtmlWriter { * @param target Target frame. * @return String Hyper Link. */ - public String getHyperLink(String link, String where, + public String getHyperLinkString(String link, String where, String label, boolean strong, String stylename, String title, String target) { StringBuffer retlink = new StringBuffer(); - retlink.append(""); } if (strong) { - retlink.append(""); + retlink.append(""); } retlink.append(label); if (strong) { - retlink.append(""); + retlink.append(""); } if (stylename != null && stylename.length() != 0) { retlink.append(""); } - retlink.append(""); + retlink.append(""); return retlink.toString(); } /** - * Print link without positioning in the file. + * Get Html Hyper Link. * * @param link String name of the file. + * @param where Position of the link in the file. Character '#' is not + * needed. * @param label Tag for the link. + * @param title String that describes the link's content for accessibility. + * @param target Target frame. + * @return a content tree for the hyper link. */ - public void printHyperLink(String link, String label) { - print(getHyperLink(link, "", label, false)); + public Content getHyperLink(String link, String where, + Content label, String title, String target) { + if (where != null && where.length() != 0) { + link += "#" + where; + } + HtmlTree anchor = HtmlTree.A(link, label); + if (title != null && title.length() != 0) { + anchor.addAttr(HtmlAttr.TITLE, title); + } + if (target != null && target.length() != 0) { + anchor.addAttr(HtmlAttr.TARGET, target); + } + return anchor; + } + + /** + * Get a hyperlink to a file. + * + * @param link String name of the file + * @param label Label for the link + * @return a content for the hyperlink to the file + */ + public Content getHyperLink(String link, Content label) { + return getHyperLink(link, "", label); } /** @@ -217,8 +258,8 @@ public abstract class HtmlDocWriter extends HtmlWriter { * @param label Tag for the link. * @return Strign Hyper link. */ - public String getHyperLink(String link, String label) { - return getHyperLink(link, "", label, false); + public String getHyperLinkString(String link, String label) { + return getHyperLinkString(link, "", label, false); } /** @@ -273,54 +314,32 @@ public abstract class HtmlDocWriter extends HtmlWriter { * Print the frameset version of the Html file header. * Called only when generating an HTML frameset file. * - * @param title Title of this HTML document. + * @param title Title of this HTML document + * @param noTimeStamp If true, don't print time stamp in header + * @param frameset the frameset to be added to the HTML document */ - public void printFramesetHeader(String title) { - printFramesetHeader(title, false); - } - - /** - * Print the frameset version of the Html file header. - * Called only when generating an HTML frameset file. - * - * @param title Title of this HTML document. - * @param noTimeStamp If true, don't print time stamp in header. - */ - public void printFramesetHeader(String title, boolean noTimeStamp) { - println(""); - println(""); - html(); - head(); + public void printFramesetDocument(String title, boolean noTimeStamp, + Content frameset) { + Content htmlDocType = DocType.Frameset(); + Content htmlComment = new Comment(configuration.getText("doclet.New_Page")); + Content head = new HtmlTree(HtmlTag.HEAD); if (! noTimeStamp) { - print(""); + Content headComment = new Comment("Generated by javadoc on " + today()); + head.addContent(headComment); } if (configuration.charset.length() > 0) { - println(""); + Content meta = HtmlTree.META("Content-Type", "text/html", + configuration.charset); + head.addContent(meta); } - title(); - println(title); - titleEnd(); - //Script to set the classFrame if necessary. - script(); - println(" targetPage = \"\" + window.location.search;"); - println(" if (targetPage != \"\" && targetPage != \"undefined\")"); - println(" targetPage = targetPage.substring(1);"); - println(" if (targetPage.indexOf(\":\") != -1)"); - println(" targetPage = \"undefined\";"); - - println(" function loadFrames() {"); - println(" if (targetPage != \"\" && targetPage != \"undefined\")"); - println(" top.classFrame.location = top.targetPage;"); - println(" }"); - scriptEnd(); - noScript(); - noScriptEnd(); - headEnd(); + Content windowTitle = HtmlTree.TITLE(new StringContent(title)); + head.addContent(windowTitle); + head.addContent(getFramesetJavaScript()); + Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), + head, frameset); + Content htmlDocument = new HtmlDocument(htmlDocType, + htmlComment, htmlTree); + print(htmlDocument.toString()); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocument.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocument.java new file mode 100644 index 00000000000..458c174ba46 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocument.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.formats.html.markup; + +import java.util.*; +import com.sun.tools.doclets.internal.toolkit.Content; +import com.sun.tools.doclets.internal.toolkit.util.*; + +/** + * Class for generating an HTML document for javadoc output. + * + * @author Bhavesh Patel + */ +public class HtmlDocument extends Content { + + private List docContent = Collections.emptyList(); + + /** + * Constructor to construct an HTML document. + * + * @param docType document type for the HTML document + * @param docComment comment for the document + * @param htmlTree HTML tree of the document + */ + public HtmlDocument(Content docType, Content docComment, Content htmlTree) { + docContent = new ArrayList(); + addContent(nullCheck(docType)); + addContent(nullCheck(docComment)); + addContent(nullCheck(htmlTree)); + } + + /** + * Constructor to construct an HTML document. + * + * @param docType document type for the HTML document + * @param htmlTree HTML tree of the document + */ + public HtmlDocument(Content docType, Content htmlTree) { + docContent = new ArrayList(); + addContent(nullCheck(docType)); + addContent(nullCheck(htmlTree)); + } + + /** + * Adds content for the HTML document. + * + * @param htmlContent html content to be added + */ + public void addContent(Content htmlContent) { + if (htmlContent.isValid()) + docContent.add(htmlContent); + } + + /** + * This method is not supported by the class. + * + * @param stringContent string content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(String stringContent) { + throw new DocletAbortException(); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return (docContent.isEmpty()); + } + + /** + * {@inheritDoc} + */ + public void write(StringBuilder contentBuilder) { + for (Content c : docContent) + c.write(contentBuilder); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java new file mode 100644 index 00000000000..3780152d99b --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.formats.html.markup; + +/** + * Enum representing HTML styles. The name map to values in the CSS file. + * + * @author Bhavesh Patel + */ +public enum HtmlStyle { + aboutLanguage, + altColor, + bar, + block, + blockList, + blockListLast, + bottomNav, + classUseContainer, + colFirst, + colLast, + colOne, + constantValuesContainer, + contentContainer, + description, + details, + header, + horizontal, + footer, + indexContainer, + indexHeader, + inheritance, + legalCopy, + nameValue, + navBarCell1Rev, + navList, + overviewSummary, + packageSummary, + rowColor, + serializedFormContainer, + sourceContainer, + sourceLineNo, + strong, + subNav, + subNavList, + subTitle, + summary, + tabEnd, + title, + topNav; +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTag.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTag.java new file mode 100644 index 00000000000..6a58bb0b3d8 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTag.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.formats.html.markup; + +/** + * Enum representing HTML tags. + * + * @author Bhavesh Patel + */ +public enum HtmlTag { + A(BlockType.INLINE, EndTag.END), + BLOCKQUOTE, + BODY(BlockType.OTHER, EndTag.END), + BR(BlockType.INLINE, EndTag.NOEND), + CAPTION, + CENTER, + CODE(BlockType.INLINE, EndTag.END), + DD, + DIV, + DL, + DT, + EM(BlockType.INLINE, EndTag.END), + FONT(BlockType.INLINE, EndTag.END), + FRAME(BlockType.OTHER, EndTag.NOEND), + FRAMESET(BlockType.OTHER, EndTag.END), + H1, + H2, + H3, + H4, + H5, + H6, + HEAD(BlockType.OTHER, EndTag.END), + HR(BlockType.BLOCK, EndTag.NOEND), + HTML(BlockType.OTHER, EndTag.END), + I(BlockType.INLINE, EndTag.END), + IMG(BlockType.INLINE, EndTag.NOEND), + LI, + LINK(BlockType.OTHER, EndTag.NOEND), + MENU, + META(BlockType.OTHER, EndTag.NOEND), + NOFRAMES(BlockType.OTHER, EndTag.END), + NOSCRIPT(BlockType.OTHER, EndTag.END), + OL, + P, + PRE, + SCRIPT(BlockType.OTHER, EndTag.END), + SMALL(BlockType.INLINE, EndTag.END), + SPAN(BlockType.INLINE, EndTag.END), + STRONG(BlockType.INLINE, EndTag.END), + TABLE, + TBODY, + TD, + TH, + TITLE(BlockType.OTHER, EndTag.END), + TR, + TT(BlockType.INLINE, EndTag.END), + UL; + + protected final BlockType blockType; + protected final EndTag endTag; + private final String value; + + /** + * Enum representing the type of HTML element. + */ + protected static enum BlockType { + BLOCK, + INLINE, + OTHER; + } + + /** + * Enum representing HTML end tag requirement. + */ + protected static enum EndTag { + END, + NOEND; + } + + HtmlTag() { + this(BlockType.BLOCK, EndTag.END); + } + + HtmlTag(BlockType blockType, EndTag endTag ) { + this.blockType = blockType; + this.endTag = endTag; + this.value = name().toLowerCase(); + } + + /** + * Returns true if the end tag is required. This is specific to the standard + * doclet and does not exactly resemble the W3C specifications. + * + * @return true if end tag needs to be displayed else return false + */ + public boolean endTagRequired() { + return (endTag == EndTag.END); + } + + public String toString() { + return value; + } +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java new file mode 100644 index 00000000000..2d2d1494299 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.formats.html.markup; + +import java.util.*; +import com.sun.tools.doclets.internal.toolkit.Content; +import com.sun.tools.doclets.internal.toolkit.util.*; + +/** + * Class for generating HTML tree for javadoc output. + * + * @author Bhavesh Patel + */ +public class HtmlTree extends Content { + + private HtmlTag htmlTag; + private Map attrs = Collections.emptyMap(); + private List content = Collections.emptyList(); + public static final Content EMPTY = new StringContent(""); + + /** + * Constructor to construct HtmlTree object. + * + * @param tag HTML tag for the HtmlTree object + */ + public HtmlTree(HtmlTag tag) { + htmlTag = nullCheck(tag); + } + + /** + * Constructor to construct HtmlTree object. + * + * @param tag HTML tag for the HtmlTree object + * @param contents contents to be added to the tree + */ + public HtmlTree(HtmlTag tag, Content... contents) { + this(tag); + for (Content content: contents) + addContent(content); + } + + /** + * Adds an attribute for the HTML tag. + * + * @param attrName name of the attribute + * @param attrValue value of the attribute + */ + public void addAttr(HtmlAttr attrName, String attrValue) { + if (attrs.isEmpty()) + attrs = new LinkedHashMap(); + attrs.put(nullCheck(attrName), nullCheck(attrValue)); + } + + /** + * Adds a style for the HTML tag. + * + * @param style style to be added + */ + public void addStyle(HtmlStyle style) { + addAttr(HtmlAttr.CLASS, style.toString()); + } + + /** + * Adds content for the HTML tag. + * + * @param tagContent tag content to be added + */ + public void addContent(Content tagContent) { + if (tagContent == HtmlTree.EMPTY || tagContent.isValid()) { + if (content.isEmpty()) + content = new ArrayList(); + content.add(tagContent); + } + } + + /** + * This method adds a string content to the htmltree. If the last content member + * added is a StringContent, append the string to that StringContent or else + * create a new StringContent and add it to the html tree. + * + * @param stringContent string content that needs to be added + */ + public void addContent(String stringContent) { + if (!content.isEmpty()) { + Content lastContent = content.get(content.size() - 1); + if (lastContent instanceof StringContent) + lastContent.addContent(stringContent); + else + addContent(new StringContent(stringContent)); + } + else + addContent(new StringContent(stringContent)); + } + + /** + * Generates an HTML anchor tag. + * + * @param ref reference url for the anchor tag + * @param body content for the anchor tag + * @return an HtmlTree object + */ + public static HtmlTree A(String ref, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.A, nullCheck(body)); + htmltree.addAttr(HtmlAttr.HREF, nullCheck(ref)); + return htmltree; + } + + /** + * Generates an HTML anchor tag with name attribute and content. + * + * @param name name for the anchor tag + * @param body content for the anchor tag + * @return an HtmlTree object + */ + public static HtmlTree A_NAME(String name, Content body) { + HtmlTree htmltree = HtmlTree.A_NAME(name); + htmltree.addContent(nullCheck(body)); + return htmltree; + } + + /** + * Generates an HTML anchor tag with name attribute. + * + * @param name name for the anchor tag + * @return an HtmlTree object + */ + public static HtmlTree A_NAME(String name) { + HtmlTree htmltree = new HtmlTree(HtmlTag.A); + htmltree.addAttr(HtmlAttr.NAME, nullCheck(name)); + return htmltree; + } + + /** + * Generates a CAPTION tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the CAPTION tag + */ + public static HtmlTree CAPTION(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.CAPTION, nullCheck(body)); + return htmltree; + } + + /** + * Generates a CODE tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the CODE tag + */ + public static HtmlTree CODE(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.CODE, nullCheck(body)); + return htmltree; + } + + /** + * Generates a DD tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the DD tag + */ + public static HtmlTree DD(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.DD, nullCheck(body)); + return htmltree; + } + + /** + * Generates a DL tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the DL tag + */ + public static HtmlTree DL(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.DL, nullCheck(body)); + return htmltree; + } + + /** + * Generates a DIV tag with the style class attributes. It also encloses + * a content. + * + * @param styleClass stylesheet class for the tag + * @param body content for the tag + * @return an HtmlTree object for the DIV tag + */ + public static HtmlTree DIV(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.DIV, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a DIV tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the DIV tag + */ + public static HtmlTree DIV(Content body) { + return DIV(null, body); + } + + /** + * Generates a DT tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the DT tag + */ + public static HtmlTree DT(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.DT, nullCheck(body)); + return htmltree; + } + + /** + * Generates a EM tag with some content. + * + * @param body content to be added to the tag + * @return an HtmlTree object for the EM tag + */ + public static HtmlTree EM(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.EM, nullCheck(body)); + return htmltree; + } + + /** + * Generates a FRAME tag. + * + * @param src the url of the document to be shown in the frame + * @param name specifies the name of the frame + * @param title the title for the frame + * @param scrolling specifies whether to display scrollbars in the frame + * @return an HtmlTree object for the FRAME tag + */ + public static HtmlTree FRAME(String src, String name, String title, String scrolling) { + HtmlTree htmltree = new HtmlTree(HtmlTag.FRAME); + htmltree.addAttr(HtmlAttr.SRC, nullCheck(src)); + htmltree.addAttr(HtmlAttr.NAME, nullCheck(name)); + htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title)); + if (scrolling != null) + htmltree.addAttr(HtmlAttr.SCROLLING, scrolling); + return htmltree; + } + + /** + * Generates a Frame tag. + * + * @param src the url of the document to be shown in the frame + * @param name specifies the name of the frame + * @param title the title for the frame + * @return an HtmlTree object for the SPAN tag + */ + public static HtmlTree FRAME(String src, String name, String title) { + return FRAME(src, name, title, null); + } + + /** + * Generates a FRAMESET tag. + * + * @param cols the size of columns in the frameset + * @param rows the size of rows in the frameset + * @param title the title for the frameset + * @param onload the script to run when the document loads + * @return an HtmlTree object for the FRAMESET tag + */ + public static HtmlTree FRAMESET(String cols, String rows, String title, String onload) { + HtmlTree htmltree = new HtmlTree(HtmlTag.FRAMESET); + if (cols != null) + htmltree.addAttr(HtmlAttr.COLS, cols); + if (rows != null) + htmltree.addAttr(HtmlAttr.ROWS, rows); + htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title)); + htmltree.addAttr(HtmlAttr.ONLOAD, nullCheck(onload)); + return htmltree; + } + + /** + * Generates a heading tag (h1 to h6) with the title and style class attributes. It also encloses + * a content. + * + * @param headingTag the heading tag to be generated + * @param printTitle true if title for the tag needs to be printed else false + * @param styleClass stylesheet class for the tag + * @param body content for the tag + * @return an HtmlTree object for the tag + */ + public static HtmlTree HEADING(HtmlTag headingTag, boolean printTitle, + HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(headingTag, nullCheck(body)); + if (printTitle) + htmltree.addAttr(HtmlAttr.TITLE, Util.stripHtml(body.toString())); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a heading tag (h1 to h6) with style class attribute. It also encloses + * a content. + * + * @param headingTag the heading tag to be generated + * @param styleClass stylesheet class for the tag + * @param body content for the tag + * @return an HtmlTree object for the tag + */ + public static HtmlTree HEADING(HtmlTag headingTag, HtmlStyle styleClass, Content body) { + return HEADING(headingTag, false, styleClass, body); + } + + /** + * Generates a heading tag (h1 to h6) with the title attribute. It also encloses + * a content. + * + * @param headingTag the heading tag to be generated + * @param printTitle true if the title for the tag needs to be printed else false + * @param body content for the tag + * @return an HtmlTree object for the tag + */ + public static HtmlTree HEADING(HtmlTag headingTag, boolean printTitle, Content body) { + return HEADING(headingTag, printTitle, null, body); + } + + /** + * Generates a heading tag (h1 to h6) with some content. + * + * @param headingTag the heading tag to be generated + * @param body content for the tag + * @return an HtmlTree object for the tag + */ + public static HtmlTree HEADING(HtmlTag headingTag, Content body) { + return HEADING(headingTag, false, null, body); + } + + /** + * Generates an HTML tag with lang attribute. It also adds head and body + * content to the HTML tree. + * + * @param lang language for the HTML document + * @param head head for the HTML tag + * @param body body for the HTML tag + * @return an HtmlTree object for the HTML tag + */ + public static HtmlTree HTML(String lang, Content head, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.HTML, nullCheck(head), nullCheck(body)); + htmltree.addAttr(HtmlAttr.LANG, nullCheck(lang)); + return htmltree; + } + + /** + * Generates a I tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the I tag + */ + public static HtmlTree I(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.I, nullCheck(body)); + return htmltree; + } + + /** + * Generates a LI tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the LI tag + */ + public static HtmlTree LI(Content body) { + return LI(null, body); + } + + /** + * Generates a LI tag with some content. + * + * @param styleClass style for the tag + * @param body content for the tag + * @return an HtmlTree object for the LI tag + */ + public static HtmlTree LI(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.LI, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a LINK tag with the rel, type, href and title attributes. + * + * @param rel relevance of the link + * @param type type of link + * @param href the path for the link + * @param title title for the link + * @return an HtmlTree object for the LINK tag + */ + public static HtmlTree LINK(String rel, String type, String href, String title) { + HtmlTree htmltree = new HtmlTree(HtmlTag.LINK); + htmltree.addAttr(HtmlAttr.REL, nullCheck(rel)); + htmltree.addAttr(HtmlAttr.TYPE, nullCheck(type)); + htmltree.addAttr(HtmlAttr.HREF, nullCheck(href)); + htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title)); + return htmltree; + } + + /** + * Generates a META tag with the http-equiv, content and charset attributes. + * + * @param http-equiv http equiv attribute for the META tag + * @param content type of content + * @param charset character set used + * @return an HtmlTree object for the META tag + */ + public static HtmlTree META(String httpEquiv, String content, String charSet) { + HtmlTree htmltree = new HtmlTree(HtmlTag.META); + htmltree.addAttr(HtmlAttr.HTTP_EQUIV, nullCheck(httpEquiv)); + htmltree.addAttr(HtmlAttr.CONTENT, nullCheck(content)); + htmltree.addAttr(HtmlAttr.CHARSET, nullCheck(charSet)); + return htmltree; + } + + /** + * Generates a META tag with the name and content attributes. + * + * @param name name attribute + * @param content type of content + * @return an HtmlTree object for the META tag + */ + public static HtmlTree META(String name, String content) { + HtmlTree htmltree = new HtmlTree(HtmlTag.META); + htmltree.addAttr(HtmlAttr.NAME, nullCheck(name)); + htmltree.addAttr(HtmlAttr.CONTENT, nullCheck(content)); + return htmltree; + } + + /** + * Generates a NOSCRIPT tag with some content. + * + * @param body content of the noscript tag + * @return an HtmlTree object for the NOSCRIPT tag + */ + public static HtmlTree NOSCRIPT(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.NOSCRIPT, nullCheck(body)); + return htmltree; + } + + /** + * Generates a P tag with some content. + * + * @param body content of the Paragraph tag + * @return an HtmlTree object for the P tag + */ + public static HtmlTree P(Content body) { + return P(null, body); + } + + /** + * Generates a P tag with some content. + * + * @param styleClass style of the Paragraph tag + * @param body content of the Paragraph tag + * @return an HtmlTree object for the P tag + */ + public static HtmlTree P(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.P, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a SMALL tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the SMALL tag + */ + public static HtmlTree SMALL(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.SMALL, nullCheck(body)); + return htmltree; + } + + /** + * Generates a STRONG tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the STRONG tag + */ + public static HtmlTree STRONG(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.STRONG, nullCheck(body)); + return htmltree; + } + + /** + * Generates a SPAN tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the SPAN tag + */ + public static HtmlTree SPAN(Content body) { + return SPAN(null, body); + } + + /** + * Generates a SPAN tag with style class attribute and some content. + * + * @param styleClass style class for the tag + * @param body content for the tag + * @return an HtmlTree object for the SPAN tag + */ + public static HtmlTree SPAN(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a Table tag with border, width and summary attributes and + * some content. + * + * @param border border for the table + * @param width width of the table + * @param summary summary for the table + * @param body content for the table + * @return an HtmlTree object for the TABLE tag + */ + public static HtmlTree TABLE(int border, int width, String summary, + Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body)); + htmltree.addAttr(HtmlAttr.BORDER, Integer.toString(border)); + htmltree.addAttr(HtmlAttr.WIDTH, Integer.toString(width)); + htmltree.addAttr(HtmlAttr.SUMMARY, nullCheck(summary)); + return htmltree; + } + + /** + * Generates a Table tag with style class, border, cell padding, + * cellspacing and summary attributes and some content. + * + * @param styleClass style of the table + * @param border border for the table + * @param cellPadding cell padding for the table + * @param cellSpacing cell spacing for the table + * @param summary summary for the table + * @param body content for the table + * @return an HtmlTree object for the TABLE tag + */ + public static HtmlTree TABLE(HtmlStyle styleClass, int border, int cellPadding, + int cellSpacing, String summary, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + htmltree.addAttr(HtmlAttr.BORDER, Integer.toString(border)); + htmltree.addAttr(HtmlAttr.CELLPADDING, Integer.toString(cellPadding)); + htmltree.addAttr(HtmlAttr.CELLSPACING, Integer.toString(cellSpacing)); + htmltree.addAttr(HtmlAttr.SUMMARY, nullCheck(summary)); + return htmltree; + } + + /** + * Generates a Table tag with border, cell padding, + * cellspacing and summary attributes and some content. + * + * @param border border for the table + * @param cellPadding cell padding for the table + * @param cellSpacing cell spacing for the table + * @param summary summary for the table + * @param body content for the table + * @return an HtmlTree object for the TABLE tag + */ + public static HtmlTree TABLE(int border, int cellPadding, + int cellSpacing, String summary, Content body) { + return TABLE(null, border, cellPadding, cellSpacing, summary, body); + } + + /** + * Generates a TD tag with style class attribute and some content. + * + * @param styleClass style for the tag + * @param body content for the tag + * @return an HtmlTree object for the TD tag + */ + public static HtmlTree TD(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TD, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a TD tag for an HTML table with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the TD tag + */ + public static HtmlTree TD(Content body) { + return TD(null, body); + } + + /** + * Generates a TH tag with style class and scope attributes and some content. + * + * @param styleClass style for the tag + * @param scope scope of the tag + * @param body content for the tag + * @return an HtmlTree object for the TH tag + */ + public static HtmlTree TH(HtmlStyle styleClass, String scope, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TH, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + htmltree.addAttr(HtmlAttr.SCOPE, nullCheck(scope)); + return htmltree; + } + + /** + * Generates a TH tag with scope attribute and some content. + * + * @param scope scope of the tag + * @param body content for the tag + * @return an HtmlTree object for the TH tag + */ + public static HtmlTree TH(String scope, Content body) { + return TH(null, scope, body); + } + + /** + * Generates a TITLE tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the TITLE tag + */ + public static HtmlTree TITLE(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TITLE, nullCheck(body)); + return htmltree; + } + + /** + * Generates a TR tag for an HTML table with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the TR tag + */ + public static HtmlTree TR(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TR, nullCheck(body)); + return htmltree; + } + + /** + * Generates a UL tag with the style class attribute and some content. + * + * @param styleClass style for the tag + * @param body content for the tag + * @return an HtmlTree object for the UL tag + */ + public static HtmlTree UL(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.UL, nullCheck(body)); + htmltree.addStyle(nullCheck(styleClass)); + return htmltree; + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return (!hasContent() && !hasAttrs()); + } + + /** + * Returns true if the HTML tree has content. + * + * @return true if the HTML tree has content else return false + */ + public boolean hasContent() { + return (!content.isEmpty()); + } + + /** + * Returns true if the HTML tree has attributes. + * + * @return true if the HTML tree has attributes else return false + */ + public boolean hasAttrs() { + return (!attrs.isEmpty()); + } + + /** + * Returns true if the HTML tree has a specific attribute. + * + * @param attrName name of the attribute to check within the HTML tree + * @return true if the HTML tree has the specified attribute else return false + */ + public boolean hasAttr(HtmlAttr attrName) { + return (attrs.containsKey(attrName)); + } + + /** + * Returns true if the HTML tree is valid. This check is more specific to + * standard doclet and not exactly similar to W3C specifications. But it + * ensures HTML validation. + * + * @return true if the HTML tree is valid + */ + public boolean isValid() { + switch (htmlTag) { + case A : + return (hasAttr(HtmlAttr.NAME) || (hasAttr(HtmlAttr.HREF) && hasContent())); + case BR : + return (!hasContent() && (!hasAttrs() || hasAttr(HtmlAttr.CLEAR))); + case FRAME : + return (hasAttr(HtmlAttr.SRC) && !hasContent()); + case HR : + return (!hasContent()); + case IMG : + return (hasAttr(HtmlAttr.SRC) && hasAttr(HtmlAttr.ALT) && !hasContent()); + case LINK : + return (hasAttr(HtmlAttr.HREF) && !hasContent()); + case META : + return (hasAttr(HtmlAttr.CONTENT) && !hasContent()); + default : + return hasContent(); + } + } + + /** + * Returns true if the element is an inline element. + * + * @return true if the HTML tag is an inline element + */ + public boolean isInline() { + return (htmlTag.blockType == HtmlTag.BlockType.INLINE); + } + + /** + * {@inheritDoc} + */ + public void write(StringBuilder contentBuilder) { + if (!isInline() && !endsWithNewLine(contentBuilder)) + contentBuilder.append("\n"); + String tagString = htmlTag.toString(); + contentBuilder.append("<" + tagString); + Iterator iterator = attrs.keySet().iterator(); + HtmlAttr key; + String value = ""; + while (iterator.hasNext()) { + key = iterator.next(); + value = attrs.get(key); + contentBuilder.append(" " + key.toString()); + if (!value.isEmpty()) + contentBuilder.append("=\"" + value + "\""); + } + contentBuilder.append(">"); + for (Content c : content) + c.write(contentBuilder); + if (htmlTag.endTagRequired()) + contentBuilder.append(""); + if (!isInline()) + contentBuilder.append("\n"); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java index 2d607af4a67..dbbc3a057d8 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java @@ -55,7 +55,7 @@ public class HtmlWriter extends PrintWriter { * URL file separator string("/"). */ public static final String fileseparator = - DirectoryManager.URL_FILE_SEPERATOR; + DirectoryManager.URL_FILE_SEPARATOR; /** * The configuration @@ -82,6 +82,72 @@ public class HtmlWriter extends PrintWriter { */ protected final String modifierTypeHeader; + public final Content overviewLabel; + + public final Content defaultPackageLabel; + + public final Content packageLabel; + + public final Content useLabel; + + public final Content prevLabel; + + public final Content nextLabel; + + public final Content prevclassLabel; + + public final Content nextclassLabel; + + public final Content summaryLabel; + + public final Content detailLabel; + + public final Content framesLabel; + + public final Content noframesLabel; + + public final Content treeLabel; + + public final Content classLabel; + + public final Content deprecatedLabel; + + public final Content deprecatedPhrase; + + public final Content allclassesLabel; + + public final Content indexLabel; + + public final Content helpLabel; + + public final Content seeLabel; + + public final Content descriptionLabel; + + public final Content prevpackageLabel; + + public final Content nextpackageLabel; + + public final Content packagesLabel; + + public final Content methodDetailsLabel; + + public final Content annotationTypeDetailsLabel; + + public final Content fieldDetailsLabel; + + public final Content constructorDetailsLabel; + + public final Content enumConstantsDetailsLabel; + + public final Content specifiedByLabel; + + public final Content overridesLabel; + + public final Content descfrmClassLabel; + + public final Content descfrmInterfaceLabel; + /** * Constructor. * @@ -111,6 +177,73 @@ public class HtmlWriter extends PrintWriter { modifierTypeHeader = configuration.getText("doclet.0_and_1", configuration.getText("doclet.Modifier"), configuration.getText("doclet.Type")); + overviewLabel = getResource("doclet.Overview"); + defaultPackageLabel = new RawHtml( + DocletConstants.DEFAULT_PACKAGE_NAME); + packageLabel = getResource("doclet.Package"); + useLabel = getResource("doclet.navClassUse"); + prevLabel = getResource("doclet.Prev"); + nextLabel = getResource("doclet.Next"); + prevclassLabel = getResource("doclet.Prev_Class"); + nextclassLabel = getResource("doclet.Next_Class"); + summaryLabel = getResource("doclet.Summary"); + detailLabel = getResource("doclet.Detail"); + framesLabel = getResource("doclet.FRAMES"); + noframesLabel = getResource("doclet.NO_FRAMES"); + treeLabel = getResource("doclet.Tree"); + classLabel = getResource("doclet.Class"); + deprecatedLabel = getResource("doclet.navDeprecated"); + deprecatedPhrase = getResource("doclet.Deprecated"); + allclassesLabel = getResource("doclet.All_Classes"); + indexLabel = getResource("doclet.Index"); + helpLabel = getResource("doclet.Help"); + seeLabel = getResource("doclet.See"); + descriptionLabel = getResource("doclet.Description"); + prevpackageLabel = getResource("doclet.Prev_Package"); + nextpackageLabel = getResource("doclet.Next_Package"); + packagesLabel = getResource("doclet.Packages"); + methodDetailsLabel = getResource("doclet.Method_Detail"); + annotationTypeDetailsLabel = getResource("doclet.Annotation_Type_Member_Detail"); + fieldDetailsLabel = getResource("doclet.Field_Detail"); + constructorDetailsLabel = getResource("doclet.Constructor_Detail"); + enumConstantsDetailsLabel = getResource("doclet.Enum_Constant_Detail"); + specifiedByLabel = getResource("doclet.Specified_By"); + overridesLabel = getResource("doclet.Overrides"); + descfrmClassLabel = getResource("doclet.Description_From_Class"); + descfrmInterfaceLabel = getResource("doclet.Description_From_Interface"); + } + + /** + * Get the configuration string as a content. + * + * @param key the key to look for in the configuration file + * @return a content tree for the text + */ + public Content getResource(String key) { + return new StringContent(configuration.getText(key)); + } + + /** + * Get the configuration string as a content. + * + * @param key the key to look for in the configuration file + * @param a1 string argument added to configuration text + * @return a content tree for the text + */ + public Content getResource(String key, String a1) { + return new RawHtml(configuration.getText(key, a1)); + } + + /** + * Get the configuration string as a content. + * + * @param key the key to look for in the configuration file + * @param a1 string argument added to configuration text + * @param a2 string argument added to configuration text + * @return a content tree for the text + */ + public Content getResource(String key, String a1, String a2) { + return new RawHtml(configuration.getText(key, a1, a2)); } /** @@ -145,6 +278,48 @@ public class HtmlWriter extends PrintWriter { } } + /** + * Returns an HtmlTree for the SCRIPT tag. + * + * @return an HtmlTree for the SCRIPT tag + */ + protected HtmlTree getWinTitleScript(){ + HtmlTree script = new HtmlTree(HtmlTag.SCRIPT); + if(winTitle != null && winTitle.length() > 0) { + script.addAttr(HtmlAttr.TYPE, "text/javascript"); + String scriptCode = "\n"; + RawHtml scriptContent = new RawHtml(scriptCode); + script.addContent(scriptContent); + } + return script; + } + + /** + * Returns a content tree for the SCRIPT tag for the main page(index.html). + * + * @return a content for the SCRIPT tag + */ + protected Content getFramesetJavaScript(){ + HtmlTree script = new HtmlTree(HtmlTag.SCRIPT); + script.addAttr(HtmlAttr.TYPE, "text/javascript"); + String scriptCode = "\n targetPage = \"\" + window.location.search;\n" + + " if (targetPage != \"\" && targetPage != \"undefined\")\n" + + " targetPage = targetPage.substring(1);\n" + + " if (targetPage.indexOf(\":\") != -1)\n" + + " targetPage = \"undefined\";\n" + + " function loadFrames() {\n" + + " if (targetPage != \"\" && targetPage != \"undefined\")\n" + + " top.classFrame.location = top.targetPage;\n" + + " }\n"; + RawHtml scriptContent = new RawHtml(scriptCode); + script.addContent(scriptContent); + return script; + } + /** * Print the Javascript <SCRIPT> start tag with its type * attribute. @@ -203,6 +378,28 @@ public class HtmlWriter extends PrintWriter { println(">"); } + /** + * Returns an HtmlTree for the BODY tag. + * + * @param includeScript set true if printing windowtitle script + * @param title title for the window + * @return an HtmlTree for the BODY tag + */ + public HtmlTree getBody(boolean includeScript, String title) { + HtmlTree body = new HtmlTree(HtmlTag.BODY); + // Set window title string which is later printed + this.winTitle = title; + // Don't print windowtitle script for overview-frame, allclasses-frame + // and package-frame + if (includeScript) { + body.addContent(getWinTitleScript()); + Content noScript = HtmlTree.NOSCRIPT( + HtmlTree.DIV(getResource("doclet.No_Script_Message"))); + body.addContent(noScript); + } + return body; + } + /** * Print </BODY> tag. Add a newline character at the end. */ @@ -228,6 +425,15 @@ public class HtmlWriter extends PrintWriter { title(); } + /** + * Returns an HtmlTree for the TITLE tag. + * + * @return an HtmlTree for the TITLE tag + */ + public HtmlTree getTitle() { + HtmlTree title = HtmlTree.TITLE(new StringContent(winTitle)); + return title; + } /** * Print </TITLE> tag. Add a newline character at the end. @@ -519,17 +725,17 @@ public class HtmlWriter extends PrintWriter { } /** - * Return, text passed, with Italics <I> and </I> tags, surrounding it. - * So if the text passed is "Hi", then string returned will be "<I>Hi</I>". + * Return, text passed, with Italics <i> and </i> tags, surrounding it. + * So if the text passed is "Hi", then string returned will be "<i>Hi</i>". * * @param text String to be printed in between <I> and </I> tags. */ public String italicsText(String text) { - return "" + text + ""; + return "" + text + ""; } public String codeText(String text) { - return "" + text + ""; + return "" + text + ""; } /** @@ -539,6 +745,13 @@ public class HtmlWriter extends PrintWriter { print(" "); } + /** + * Return "&nbsp;", non-breaking space. + */ + public Content getSpace() { + return RawHtml.nbsp; + } + /** * Print <DL> tag. Add a newline character at the end. */ @@ -1182,21 +1395,21 @@ public class HtmlWriter extends PrintWriter { } /** - * Get the "<CODE>" string. + * Get the "<code>" string. * - * @return String Return String "<CODE>"; + * @return String Return String "<code>"; */ public String getCode() { - return ""; + return ""; } /** - * Get the "</CODE>" string. + * Get the "</code>" string. * - * @return String Return String "</CODE>"; + * @return String Return String "</code>"; */ public String getCodeEnd() { - return ""; + return ""; } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/RawHtml.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/RawHtml.java new file mode 100644 index 00000000000..56c23965534 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/RawHtml.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.formats.html.markup; + +import com.sun.tools.doclets.internal.toolkit.Content; +import com.sun.tools.doclets.internal.toolkit.util.*; + +/** + * Class for generating raw HTML content to be added to HTML pages of javadoc output. + * + * @author Bhavesh Patel + */ +public class RawHtml extends Content{ + + private String rawHtmlContent; + + public static final Content nbsp = new RawHtml(" "); + + /** + * Constructor to construct a RawHtml object. + * + * @param rawHtml raw HTML text to be added + */ + public RawHtml(String rawHtml) { + rawHtmlContent = nullCheck(rawHtml); + } + + /** + * This method is not supported by the class. + * + * @param content content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(Content content) { + throw new DocletAbortException(); + } + + /** + * This method is not supported by the class. + * + * @param stringContent string content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(String stringContent) { + throw new DocletAbortException(); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return rawHtmlContent.isEmpty(); + } + + /** + * {@inheritDoc} + */ + public void write(StringBuilder contentBuilder) { + contentBuilder.append(rawHtmlContent); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/StringContent.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/StringContent.java new file mode 100644 index 00000000000..2bf4437fb31 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/StringContent.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.formats.html.markup; + +import com.sun.tools.doclets.internal.toolkit.Content; +import com.sun.tools.doclets.internal.toolkit.util.*; + +/** + * Class for generating string content for HTML tags of javadoc output. + * + * @author Bhavesh Patel + */ +public class StringContent extends Content{ + + private StringBuilder stringContent; + + /** + * Constructor to construct StringContent object. + */ + public StringContent() { + stringContent = new StringBuilder(); + } + + /** + * Constructor to construct StringContent object with some initial content. + * + * @param initialContent initial content for the object + */ + public StringContent(String initialContent) { + stringContent = new StringBuilder( + Util.escapeHtmlChars(nullCheck(initialContent))); + } + + /** + * This method is not supported by the class. + * + * @param content content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(Content content) { + throw new DocletAbortException(); + } + + /** + * Adds content for the StringContent object. The method escapes + * HTML characters for the string content that is added. + * + * @param strContent string content to be added + */ + public void addContent(String strContent) { + stringContent.append(Util.escapeHtmlChars(nullCheck(strContent))); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return (stringContent.length() == 0); + } + + /** + * {@inheritDoc} + */ + public String toString() { + return stringContent.toString(); + } + + /** + * {@inheritDoc} + */ + public void write(StringBuilder contentBuilder) { + contentBuilder.append(stringContent); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties index 598cc88d74b..46a783c1b90 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties @@ -43,6 +43,7 @@ doclet.Window_Single_Index=Index doclet.Window_Split_Index={0}-Index doclet.Help=Help doclet.Skip_navigation_links=Skip navigation links +doclet.New_Page=NewPage doclet.None=None doclet.CLASSES=CLASSES doclet.MEMBERS=MEMBERS @@ -53,7 +54,7 @@ doclet.Deprecated_List=Deprecated List doclet.Window_Deprecated_List=Deprecated List doclet.Note_0_is_deprecated=Note: {0} is deprecated. doclet.Overrides=Overrides: -doclet.in_class={0} in class {1} +doclet.in_class=in class doclet.0_Fields_and_Methods="{0}" Fields and Methods doclet.Index_of_Fields_and_Methods=Index of Fields and Methods doclet.Static_variable_in=Static variable in {0} @@ -103,7 +104,7 @@ doclet.Other_Packages=Other Packages doclet.Package_Description=Package {0} Description doclet.Description=Description doclet.Specified_By=Specified by: -doclet.in_interface={0} in interface {1} +doclet.in_interface=in interface doclet.Subclasses=Direct Known Subclasses: doclet.Subinterfaces=All Known Subinterfaces: doclet.Implementing_Classes=All Known Implementing Classes: @@ -121,18 +122,20 @@ doclet.Cannot_handle_no_packages=Cannot handle no packages. doclet.Frame_Alert=Frame Alert doclet.Overview-Member-Frame=Overview Member Frame doclet.Frame_Warning_Message=This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. +doclet.No_Script_Message=JavaScript is disabled on your browser. doclet.Non_Frame_Version=Non-frame version. doclet.Frame_Version=Frame version doclet.Link_To=Link to doclet.Following_From_Class=Following copied from class: {0} doclet.Following_From_Interface=Following copied from interface: {0} -doclet.Description_From_Interface=Description copied from interface: {0} -doclet.Description_From_Class=Description copied from class: {0} +doclet.Description_From_Interface=Description copied from interface: +doclet.Description_From_Class=Description copied from class: doclet.Standard_doclet_invoked=Standard doclet invoked... doclet.No_Non_Deprecated_Classes_To_Document=No non-deprecated classes found to document. doclet.Interfaces_Italic=Interfaces (italic) doclet.Enclosing_Class=Enclosing class: doclet.Enclosing_Interface=Enclosing interface: +doclet.Window_Source_title=Source code doclet.Help_title=API Help doclet.Window_Help_title=API Help doclet.Help_line_1=How This API Document Is Organized diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeOptionalMemberWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeOptionalMemberWriter.java index b823eb2ca42..f31de8eca10 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeOptionalMemberWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeOptionalMemberWriter.java @@ -35,14 +35,18 @@ import com.sun.javadoc.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public interface AnnotationTypeOptionalMemberWriter extends - AnnotationTypeRequiredMemberWriter { + AnnotationTypeRequiredMemberWriter { /** - * Write the default value documentation. + * Add the the default value documentation. + * + * @param member the member being documented + * @param annotationDocTree content tree to which the default value will be added */ - public void writeDefaultValueInfo(MemberDoc member); + public void addDefaultValueInfo(MemberDoc member, Content annotationDocTree); } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java index 60f4912da21..b17040c304a 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java @@ -36,67 +36,79 @@ import com.sun.javadoc.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public interface AnnotationTypeRequiredMemberWriter { /** - * Write the header for the member documentation. + * Add the annotation type details tree header. * - * @param classDoc the annotation type that the members belong to. - * @param header the header to write. + * @param classDoc the annotation type being documented + * @param memberDetailsTree the content tree representing member details */ - public void writeHeader(ClassDoc classDoc, String header); + public void addAnnotationDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree); /** - * Write the member header for the given member. + * Get the annotation type documentation tree header. * - * @param member the member being documented. - * @param isFirst the flag to indicate whether or not the member is - * the first to be documented. + * @param member the annotation type being documented + * @param annotationDetailsTree the content tree representing annotation type details + * @return content tree for the annotation type documentation header */ - public void writeMemberHeader(MemberDoc member, boolean isFirst); + public Content getAnnotationDocTreeHeader(MemberDoc member, + Content annotationDetailsTree); /** - * Write the signature for the given member. + * Get the annotation type details tree. * - * @param member the member being documented. + * @param annotationDetailsTree the content tree representing annotation type details + * @return content tree for the annotation type details */ - public void writeSignature(MemberDoc member); + public Content getAnnotationDetails(Content annotationDetailsTree); /** - * Write the deprecated output for the given member. + * Get the annotation type documentation. * - * @param member the member being documented. + * @param annotationDocTree the content tree representing annotation type documentation + * @param isLastContent true if the content to be added is the last content + * @return content tree for the annotation type documentation */ - public void writeDeprecated(MemberDoc member); + public Content getAnnotationDoc(Content annotationDocTree, boolean isLastContent); /** - * Write the comments for the given member. + * Get the signature for the given member. * - * @param member the member being documented. + * @param member the member being documented + * @return content tree for the annotation type signature */ - public void writeComments(MemberDoc member); + public Content getSignature(MemberDoc member); /** - * Write the tag output for the given member. + * Add the deprecated output for the given member. * - * @param member the member being documented. + * @param member the member being documented + * @param annotationDocTree content tree to which the deprecated information will be added */ - public void writeTags(MemberDoc member); + public void addDeprecated(MemberDoc member, Content annotationDocTree); /** - * Write the member footer. + * Add the comments for the given member. + * + * @param member the member being documented + * @param annotationDocTree the content tree to which the comments will be added */ - public void writeMemberFooter(); + public void addComments(MemberDoc member, Content annotationDocTree); /** - * Write the footer for the member documentation. + * Add the tags for the given member. * - * @param classDoc the class that the member belong to. + * @param member the member being documented + * @param annotationDocTree the content tree to which the tags will be added */ - public void writeFooter(ClassDoc classDoc); + public void addTags(MemberDoc member, Content annotationDocTree); /** * Close the writer. diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java index 51c037aced6..357ce28b11a 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java @@ -37,43 +37,122 @@ import com.sun.javadoc.*; * Do not use it as an API. * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public interface AnnotationTypeWriter { /** - * Write the header of the page. - * @param header the header to write. + * Get the header of the page. + * + * @param header the header string to write + * @return a content tree for the header documentation */ - public void writeHeader(String header); + public Content getHeader(String header); /** - * Write the signature of the current annotation type. + * Get the annotation content header. * - * @param modifiers the modifiers for the signature. + * @return annotation content header that needs to be added to the documentation */ - public void writeAnnotationTypeSignature(String modifiers); + public Content getAnnotationContentHeader(); + + /** + * Get the annotation information tree header. + * + * @return annotation information tree header that needs to be added to the documentation + */ + public Content getAnnotationInfoTreeHeader(); + + /** + * Get the annotation information. + * + * @param annotationInfoTree content tree containing the annotation information + * @return a content tree for the annotation + */ + public Content getAnnotationInfo(Content annotationInfoTree); + + /** + * Add the signature of the current annotation type. + * + * @param modifiers the modifiers for the signature + * @param annotationInfoTree the annotation content tree to which the signature will be added + */ + public void addAnnotationTypeSignature(String modifiers, Content annotationInfoTree); /** * Build the annotation type description. + * + * @param annotationInfoTree content tree to which the description will be added */ - public void writeAnnotationTypeDescription(); + public void addAnnotationTypeDescription(Content annotationInfoTree); /** - * Write the tag information for the current annotation type. + * Add the tag information for the current annotation type. + * + * @param annotationInfoTree content tree to which the tag information will be added */ - public void writeAnnotationTypeTagInfo(); + public void addAnnotationTypeTagInfo(Content annotationInfoTree); /** - * If this annotation type is deprecated, write the appropriate information. + * If this annotation is deprecated, add the appropriate information. + * + * @param annotationInfoTree content tree to which the deprecated information will be added */ - public void writeAnnotationTypeDeprecationInfo(); + public void addAnnotationTypeDeprecationInfo (Content annotationInfoTree); /** - * Write the footer of the page. + * Add the annotation type details marker. + * + * @param memberDetails the content tree representing member details marker */ - public void writeFooter(); + public void addAnnotationDetailsMarker(Content memberDetails); + + /** + * Get the member tree header for the annotation type. + * + * @return a content tree for the member tree header + */ + public Content getMemberTreeHeader(); + + /** + * Get the member tree. + * + * @param memberTree the content tree that will be modified and returned + * @return a content tree for the member + */ + public Content getMemberTree(Content memberTree); + + /** + * Get the member summary tree. + * + * @param memberTree the content tree that will be used to build the summary tree + * @return a content tree for the member summary + */ + public Content getMemberSummaryTree(Content memberTree); + + /** + * Get the member details tree. + * + * @param memberTree the content tree that will be used to build the details tree + * @return a content tree for the member details + */ + public Content getMemberDetailsTree(Content memberTree); + + /** + * Add the footer of the page. + * + * @param contentTree content tree to which the footer will be added + */ + public void addFooter(Content contentTree); + + /** + * Print the document. + * + * @param contentTree content tree that will be printed as a document + */ + public void printDocument(Content contentTree); /** * Close the writer. @@ -86,10 +165,4 @@ public interface AnnotationTypeWriter { * @return the AnnotationTypeDoc being documented. */ public AnnotationTypeDoc getAnnotationTypeDoc(); - - /** - * Perform any operations that are necessary when the member summary - * finished building. - */ - public void completeMemberSummaryBuild(); } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ClassWriter.java index 5af17724ae7..999019d0a57 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ClassWriter.java @@ -37,85 +37,149 @@ import com.sun.javadoc.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public interface ClassWriter { /** - * Write the header of the page. - * @param header the header to write. - */ - public void writeHeader(String header); - - /** - * Write the class tree documentation. - */ - public void writeClassTree(); - - /** - * Write all implemented interfaces if this is a class. - */ - public void writeImplementedInterfacesInfo(); - - /** - * Write all super interfaces if this is an interface. - */ - public void writeSuperInterfacesInfo(); - - /** - * Write the type parameter information. - */ - public void writeTypeParamInfo(); - - /** - * Write all the classes that extend this one. - */ - public void writeSubClassInfo(); - - /** - * Write all the interfaces that extend this one. - */ - public void writeSubInterfacesInfo(); - - /** - * If this is an interface, write all classes that implement this - * interface. - */ - public void writeInterfaceUsageInfo (); - - /** - * If this is an inner class or interface, write the enclosing class or - * interface. - */ - public void writeNestedClassInfo (); - - /** - * If this class is deprecated, write the appropriate information. - */ - public void writeClassDeprecationInfo (); - - /** - * Write the signature of the current class. + * Get the header of the page. * - * @param modifiers the modifiers for the signature. + * @param header the header string to write + * @return header content that needs to be added to the documentation */ - public void writeClassSignature(String modifiers); + public Content getHeader(String header); + + /** + * Get the class content header. + * + * @return class content header that needs to be added to the documentation + */ + public Content getClassContentHeader(); + + /** + * Add the class tree documentation. + * + * @param classContentTree class content tree to which the documentation will be added + */ + public void addClassTree(Content classContentTree); + + /** + * Get the class information tree header. + * + * @return class informaion tree header that needs to be added to the documentation + */ + public Content getClassInfoTreeHeader(); + + /** + * Add the type parameter information. + * + * @param classInfoTree content tree to which the documentation will be added + */ + public void addTypeParamInfo(Content classInfoTree); + + /** + * Add all super interfaces if this is an interface. + * + * @param classInfoTree content tree to which the documentation will be added + */ + public void addSuperInterfacesInfo(Content classInfoTree); + + /** + * Add all implemented interfaces if this is a class. + * + * @param classInfoTree content tree to which the documentation will be added + */ + public void addImplementedInterfacesInfo(Content classInfoTree); + + /** + * Add all the classes that extend this one. + * + * @param classInfoTree content tree to which the documentation will be added + */ + public void addSubClassInfo(Content classInfoTree); + + /** + * Add all the interfaces that extend this one. + * + * @param classInfoTree content tree to which the documentation will be added + */ + public void addSubInterfacesInfo(Content classInfoTree); + + /** + * If this is an interface, add all classes that implement this + * interface. + * + * @param classInfoTree content tree to which the documentation will be added + */ + public void addInterfaceUsageInfo(Content classInfoTree); + + /** + * If this is an inner class or interface, add the enclosing class or + * interface. + * + * @param classInfoTree content tree to which the documentation will be added + */ + public void addNestedClassInfo (Content classInfoTree); + + /** + * Get the class information. + * + * @param classInfoTree content tree conatining the class information + * @return a content tree for the class + */ + public Content getClassInfo(Content classInfoTree); + + /** + * If this class is deprecated, add the appropriate information. + * + * @param classInfoTree content tree to which the documentation will be added + */ + public void addClassDeprecationInfo (Content classInfoTree); + + /** + * Add the signature of the current class content tree. + * + * @param modifiers the modifiers for the signature + * @param classInfoTree the class content tree to which the signature will be added + */ + public void addClassSignature(String modifiers, Content classInfoTree); /** * Build the class description. + * + * @param classInfoTree content tree to which the documentation will be added */ - public void writeClassDescription(); + public void addClassDescription(Content classInfoTree); /** - * Write the tag information for the current class. + * Add the tag information for the current class. + * + * @param classInfoTree content tree to which the tag information will be added */ - public void writeClassTagInfo(); + public void addClassTagInfo(Content classInfoTree); /** - * Write the footer of the page. + * Get the member tree header for the class. + * + * @return a content tree for the member tree header */ - public void writeFooter(); + public Content getMemberTreeHeader(); + + /** + * Add the footer of the page. + * + * @param contentTree content tree to which the footer will be added + */ + public void addFooter(Content contentTree); + + /** + * Print the document. + * + * @param contentTree content tree that will be printed as a document + */ + public void printDocument(Content contentTree); /** * Close the writer. @@ -130,8 +194,18 @@ public interface ClassWriter { public ClassDoc getClassDoc(); /** - * Perform any operations that are necessary when the member summary - * finished building. + * Get the member summary tree. + * + * @param memberTree the content tree used to build the summary tree + * @return a content tree for the member summary */ - public void completeMemberSummaryBuild(); + public Content getMemberSummaryTree(Content memberTree); + + /** + * Get the member details tree. + * + * @param memberTree the content tree used to build the details tree + * @return a content tree for the member details + */ + public Content getMemberDetailsTree(Content memberTree); } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ConstantsSummaryWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ConstantsSummaryWriter.java index 5c7133232b4..6598ee81043 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ConstantsSummaryWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ConstantsSummaryWriter.java @@ -25,9 +25,9 @@ package com.sun.tools.doclets.internal.toolkit; -import com.sun.javadoc.*; import java.util.*; import java.io.*; +import com.sun.javadoc.*; /** * The interface for writing constants summary output. @@ -37,38 +37,34 @@ import java.io.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public interface ConstantsSummaryWriter { - /** - * Write the header for the summary. - */ - public abstract void writeHeader(); - - /** - * Write the footer for the summary. - */ - public abstract void writeFooter(); - /** * Close the writer. */ public abstract void close() throws IOException; /** - * Write the header for the index. + * Get the header for the constant summary documentation. + * + * @return header that needs to be added to the documentation */ - public abstract void writeContentsHeader(); + public abstract Content getHeader(); /** - * Write the footer for the index. + * Get the header for the constant content list. + * + * @return content header that needs to be added to the documentation */ - public abstract void writeContentsFooter(); + public abstract Content getContentsHeader(); /** - * Add the given package name to the index. + * Adds the given package name link to the constant content list tree. + * * @param pkg the {@link PackageDoc} to index. * @param parsedPackageName the parsed package name. We only Write the * first 2 directory levels of the package @@ -77,38 +73,70 @@ public interface ConstantsSummaryWriter { * @param WriteedPackageHeaders the set of package headers that have already * been indexed. We don't want to index * something more than once. + * @param contentListTree the content tree to which the link will be added */ - public abstract void writeLinkToPackageContent(PackageDoc pkg, String parsedPackageName, - Set WriteedPackageHeaders); + public abstract void addLinkToPackageContent(PackageDoc pkg, String parsedPackageName, + Set WriteedPackageHeaders, Content contentListTree); /** - * Write the given package name. - * @param pkg the {@link PackageDoc} to index. - * @param parsedPackageName the parsed package name. We only Write the - * first 2 directory levels of the package - * name. For example, java.lang.ref would be - * indexed as java.lang.*. + * Get the content list to be added to the documentation tree. + * + * @param contentListTree the content that will be added to the list + * @return content list that will be added to the documentation tree */ - public abstract void writePackageName(PackageDoc pkg, - String parsedPackageName); + public abstract Content getContentsList(Content contentListTree); /** - * Write the heading for the current table of constants for a given class. - * @param cd the class whose constants are being documented. + * Get the constant summaries for the document. + * + * @return constant summaries header to be added to the documentation tree */ - public abstract void writeConstantMembersHeader(ClassDoc cd); + public abstract Content getConstantSummaries(); /** - * Document the given constants. + * Adds the given package name. + * + * @param pkg the {@link PackageDoc} to index. + * @param parsedPackageName the parsed package name. We only Write the + * first 2 directory levels of the package + * name. For example, java.lang.ref would be + * indexed as java.lang.*. + * @param summariesTree the documentation tree to which the package name will + * be written + */ + public abstract void addPackageName(PackageDoc pkg, + String parsedPackageName, Content summariesTree); + + /** + * Get the class summary header for the constants summary. + * + * @return the header content for the class constants summary + */ + public abstract Content getClassConstantHeader(); + + /** + * Adds the constant member table to the documentation tree. + * * @param cd the class whose constants are being documented. * @param fields the constants being documented. + * @param classConstantTree the documentation tree to which theconstant member + * table content will be added */ - public abstract void writeConstantMembers(ClassDoc cd, List fields); + public abstract void addConstantMembers(ClassDoc cd, List fields, + Content classConstantTree); /** - * Document the given constants. - * @param cd the class whose constants are being documented. + * Adds the footer for the summary documentation. + * + * @param contentTree content tree to which the footer will be added */ - public abstract void writeConstantMembersFooter(ClassDoc cd); + public abstract void addFooter(Content contentTree); + + /** + * Print the constants summary document. + * + * @param contentTree content tree which should be printed + */ + public abstract void printDocument(Content contentTree); } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ConstructorWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ConstructorWriter.java index 397a4f31011..a120a5405c1 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ConstructorWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/ConstructorWriter.java @@ -36,67 +36,80 @@ import com.sun.javadoc.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public interface ConstructorWriter { /** - * Write the header for the constructor documentation. + * Get the constructor details tree header. * - * @param classDoc the class that the constructors belong to. - * @param header the header to write. + * @param classDoc the class being documented + * @param memberDetailsTree the content tree representing member details + * @return content tree for the constructor details header */ - public void writeHeader(ClassDoc classDoc, String header); + public Content getConstructorDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree); /** - * Write the constructor header for the given constructor. + * Get the constructor documentation tree header. * - * @param constructor the constructor being documented. - * @param isFirst the flag to indicate whether or not the constructor is the - * first to be documented. + * @param constructor the constructor being documented + * @param constructorDetailsTree the content tree representing constructor details + * @return content tree for the constructor documentation header */ - public void writeConstructorHeader(ConstructorDoc constructor, boolean isFirst); + public Content getConstructorDocTreeHeader(ConstructorDoc constructor, + Content constructorDetailsTree); /** - * Write the signature for the given constructor. + * Get the signature for the given constructor. * - * @param constructor the constructor being documented. + * @param constructor the constructor being documented + * @return content tree for the constructor signature */ - public void writeSignature(ConstructorDoc constructor); + public Content getSignature(ConstructorDoc constructor); /** - * Write the deprecated output for the given constructor. + * Add the deprecated output for the given constructor. * - * @param constructor the constructor being documented. + * @param constructor the constructor being documented + * @param constructorDocTree content tree to which the deprecated information will be added */ - public void writeDeprecated(ConstructorDoc constructor); + public void addDeprecated(ConstructorDoc constructor, Content constructorDocTree); /** - * Write the comments for the given constructor. + * Add the comments for the given constructor. * - * @param constructor the constructor being documented. + * @param constructor the constructor being documented + * @param constructorDocTree the content tree to which the comments will be added */ - public void writeComments(ConstructorDoc constructor); + public void addComments(ConstructorDoc constructor, Content constructorDocTree); /** - * Write the tag output for the given constructor. + * Add the tags for the given constructor. * - * @param constructor the constructor being documented. + * @param constructor the constructor being documented + * @param constructorDocTree the content tree to which the tags will be added */ - public void writeTags(ConstructorDoc constructor); + public void addTags(ConstructorDoc constructor, Content constructorDocTree); /** - * Write the constructor footer. + * Get the constructor details tree. + * + * @param memberDetailsTree the content tree representing member details + * @return content tree for the constructor details */ - public void writeConstructorFooter(); + public Content getConstructorDetails(Content memberDetailsTree); /** - * Write the footer for the constructor documentation. + * Get the constructor documentation. * - * @param classDoc the class that the constructors belong to. + * @param constructorDocTree the content tree representing constructor documentation + * @param isLastContent true if the content to be added is the last content + * @return content tree for the constructor documentation */ - public void writeFooter(ClassDoc classDoc); + public Content getConstructorDoc(Content constructorDocTree, boolean isLastContent); /** * Let the writer know whether a non public constructor was found. diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Content.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Content.java new file mode 100644 index 00000000000..80d624c3ebf --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Content.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.internal.toolkit; + +import com.sun.tools.doclets.internal.toolkit.util.*; + +/** + * A class to create content for javadoc output pages. + * + * @author Bhavesh Patel + */ +public abstract class Content { + + /** + * Returns a string representation of the content. + * + * @return string representation of the content + */ + public String toString() { + StringBuilder contentBuilder = new StringBuilder(); + write(contentBuilder); + return contentBuilder.toString(); + } + + /** + * Adds content to the existing content. + * + * @param content content that needs to be added + */ + public abstract void addContent(Content content); + + /** + * Adds a string content to the existing content. + * + * @param stringContent the string content to be added + */ + public abstract void addContent(String stringContent); + + /** + * Writes content to a StringBuilder. + * + */ + public abstract void write(StringBuilder contentBuilder); + + /** + * Returns true if the content is empty. + * + * @return true if no content to be displayed else return false + */ + public abstract boolean isEmpty(); + + /** + * Returns true if the content is valid. + * + * @return true if the content is valid else return false + */ + public boolean isValid() { + return !isEmpty(); + } + + /** + * Checks for null values. + * + * @param t reference type to check for null values + * @return the reference type if not null or else throws a null pointer exception + */ + protected static T nullCheck(T t) { + t.getClass(); + return t; + } + + /** + * Returns true if the content ends with a newline character. Empty content + * is considered as ending with new line. + * + * @param contentBuilder content to test for newline character at the end + * @return true if the content ends with newline. + */ + public boolean endsWithNewLine(StringBuilder contentBuilder) { + return ((contentBuilder.length() == 0) || + (contentBuilder.substring(contentBuilder.length() - 1).equals("\n"))); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/EnumConstantWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/EnumConstantWriter.java index 15db4e7cb5c..bd41497606e 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/EnumConstantWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/EnumConstantWriter.java @@ -36,67 +36,80 @@ import com.sun.javadoc.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public interface EnumConstantWriter { /** - * Write the header for the enum constant documentation. + * Get the enum constants details tree header. * - * @param classDoc the class that the enum constants belong to. - * @param header the header to write. + * @param classDoc the class being documented + * @param memberDetailsTree the content tree representing member details + * @return content tree for the enum constants details header */ - public void writeHeader(ClassDoc classDoc, String header); + public Content getEnumConstantsDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree); /** - * Write the enum constant header for the given enum constant. + * Get the enum constants documentation tree header. * - * @param enumConstant the enum constant being documented. - * @param isFirst the flag to indicate whether or not the enum constant is - * the first to be documented. + * @param enumConstant the enum constant being documented + * @param enumConstantDetailsTree the content tree representing enum constant details + * @return content tree for the enum constant documentation header */ - public void writeEnumConstantHeader(FieldDoc enumConstant, boolean isFirst); + public Content getEnumConstantsTreeHeader(FieldDoc enumConstant, + Content enumConstantsDetailsTree); /** - * Write the signature for the given enum constant. + * Get the signature for the given enum constant. * - * @param enumConstant the enum constant being documented. + * @param enumConstant the enum constant being documented + * @return content tree for the enum constant signature */ - public void writeSignature(FieldDoc enumConstant); + public Content getSignature(FieldDoc enumConstant); /** - * Write the deprecated output for the given enum constant. + * Add the deprecated output for the given enum constant. * - * @param enumConstant the enum constant being documented. + * @param enumConstant the enum constant being documented + * @param enumConstantsTree content tree to which the deprecated information will be added */ - public void writeDeprecated(FieldDoc enumConstant); + public void addDeprecated(FieldDoc enumConstant, Content enumConstantsTree); /** - * Write the comments for the given enum constant. + * Add the comments for the given enum constant. * - * @param enumConstant the enum constant being documented. + * @param enumConstant the enum constant being documented + * @param enumConstantsTree the content tree to which the comments will be added */ - public void writeComments(FieldDoc enumConstant); + public void addComments(FieldDoc enumConstant, Content enumConstantsTree); /** - * Write the tag output for the given enum constant. + * Add the tags for the given enum constant. * - * @param enumConstant the enum constant being documented. + * @param enumConstant the enum constant being documented + * @param enumConstantsTree the content tree to which the tags will be added */ - public void writeTags(FieldDoc enumConstant); + public void addTags(FieldDoc enumConstant, Content enumConstantsTree); /** - * Write the enum constant footer. + * Get the enum constants details tree. + * + * @param memberDetailsTree the content tree representing member details + * @return content tree for the enum constant details */ - public void writeEnumConstantFooter(); + public Content getEnumConstantsDetails(Content memberDetailsTree); /** - * Write the footer for the enum constant documentation. + * Get the enum constants documentation. * - * @param classDoc the class that the enum constant belong to. + * @param enumConstantsTree the content tree representing enum constants documentation + * @param isLastContent true if the content to be added is the last content + * @return content tree for the enum constants documentation */ - public void writeFooter(ClassDoc classDoc); + public Content getEnumConstants(Content enumConstantsTree, boolean isLastContent); /** * Close the writer. diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/FieldWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/FieldWriter.java index 401eb30a343..637466caacb 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/FieldWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/FieldWriter.java @@ -36,67 +36,80 @@ import com.sun.javadoc.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public interface FieldWriter { /** - * Write the header for the field documentation. + * Get the field details tree header. * - * @param classDoc the class that the fields belong to. - * @param header the header to write. + * @param classDoc the class being documented + * @param memberDetailsTree the content tree representing member details + * @return content tree for the field details header */ - public void writeHeader(ClassDoc classDoc, String header); + public Content getFieldDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree); /** - * Write the field header for the given field. + * Get the field documentation tree header. * - * @param field the field being documented. - * @param isFirst the flag to indicate whether or not the field is the - * first to be documented. + * @param field the constructor being documented + * @param fieldDetailsTree the content tree representing field details + * @return content tree for the field documentation header */ - public void writeFieldHeader(FieldDoc field, boolean isFirst); + public Content getFieldDocTreeHeader(FieldDoc field, + Content fieldDetailsTree); /** - * Write the signature for the given field. + * Get the signature for the given field. * - * @param field the field being documented. + * @param field the field being documented + * @return content tree for the field signature */ - public void writeSignature(FieldDoc field); + public Content getSignature(FieldDoc field); /** - * Write the deprecated output for the given field. + * Add the deprecated output for the given field. * - * @param field the field being documented. + * @param field the field being documented + * @param fieldDocTree content tree to which the deprecated information will be added */ - public void writeDeprecated(FieldDoc field); + public void addDeprecated(FieldDoc field, Content fieldDocTree); /** - * Write the comments for the given field. + * Add the comments for the given field. * - * @param field the field being documented. + * @param field the field being documented + * @param fieldDocTree the content tree to which the comments will be added */ - public void writeComments(FieldDoc field); + public void addComments(FieldDoc field, Content fieldDocTree); /** - * Write the tag output for the given field. + * Add the tags for the given field. * - * @param field the field being documented. + * @param field the field being documented + * @param fieldDocTree the content tree to which the tags will be added */ - public void writeTags(FieldDoc field); + public void addTags(FieldDoc field, Content fieldDocTree); /** - * Write the field footer. + * Get the field details tree. + * + * @param memberDetailsTree the content tree representing member details + * @return content tree for the field details */ - public void writeFieldFooter(); + public Content getFieldDetails(Content memberDetailsTree); /** - * Write the footer for the field documentation. + * Get the field documentation. * - * @param classDoc the class that the fields belong to. + * @param fieldDocTree the content tree representing field documentation + * @param isLastContent true if the content to be added is the last content + * @return content tree for the field documentation */ - public void writeFooter(ClassDoc classDoc); + public Content getFieldDoc(Content fieldDocTree, boolean isLastContent); /** * Close the writer. diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/MemberSummaryWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/MemberSummaryWriter.java index 64a87a0fab2..a7e39ebc4c2 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/MemberSummaryWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/MemberSummaryWriter.java @@ -26,6 +26,7 @@ package com.sun.tools.doclets.internal.toolkit; import java.io.*; +import java.util.*; import com.sun.javadoc.*; /** @@ -36,61 +37,77 @@ import com.sun.javadoc.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public interface MemberSummaryWriter { /** - * Write the member summary header for the given class. + * Get the member summary header for the given class. * - * @param classDoc the class the summary belongs to. + * @param classDoc the class the summary belongs to + * @param memberSummaryTree the content tree to which the member summary will be added + * @return a content tree for the member summary header */ - public void writeMemberSummaryHeader(ClassDoc classDoc); + public Content getMemberSummaryHeader(ClassDoc classDoc, + Content memberSummaryTree); /** - * Write the member summary for the given class and member. + * Get the summary table for the given class. * - * @param classDoc the class the summary belongs to. - * @param member the member that I am summarizing. - * @param firstSentenceTags the tags for the sentence being documented. - * @param isFirst true if this is the first member in the list. - * @param isLast true if this the last member being documented. + * @param classDoc the class the summary table belongs to + * @return a content tree for the member summary table */ - public void writeMemberSummary(ClassDoc classDoc, ProgramElementDoc member, - Tag[] firstSentenceTags, boolean isFirst, boolean isLast); + public Content getSummaryTableTree(ClassDoc classDoc); /** - * Write the member summary footer for the given class. + * Add the member summary for the given class and member. * - * @param classDoc the class the summary belongs to. + * @param classDoc the class the summary belongs to + * @param member the member that is documented + * @param firstSentenceTags the tags for the sentence being documented + * @param tableTree the content treeto which the information will be added + * @param counter the counter for determing style for the table row */ - public void writeMemberSummaryFooter(ClassDoc classDoc); + public void addMemberSummary(ClassDoc classDoc, ProgramElementDoc member, + Tag[] firstSentenceTags, Content tableTree, int counter); /** - * Write the inherited member summary header for the given class. + * Get the inherited member summary header for the given class. * - * @param classDoc the class the summary belongs to. + * @param classDoc the class the summary belongs to + * @return a content tree containing the inherited summary header */ - public void writeInheritedMemberSummaryHeader(ClassDoc classDoc); + public Content getInheritedSummaryHeader(ClassDoc classDoc); /** - * Write the inherited member summary for the given class and member. + * Add the inherited member summary for the given class and member. * - * @param classDoc the class the inherited member belongs to. - * @param member the inherited member that I am summarizing. - * @param isFirst true if this is the first member in the list. - * @param isLast true if this is the last member in the list. + * @param classDoc the class the inherited member belongs to + * @param member the inherited member that is being documented + * @param isFirst true if this is the first member in the list + * @param isLast true if this is the last member in the list + * @param linksTree the content tree to which the links will be added */ - public void writeInheritedMemberSummary(ClassDoc classDoc, - ProgramElementDoc member, boolean isFirst, boolean isLast); + public void addInheritedMemberSummary(ClassDoc classDoc, + ProgramElementDoc member, boolean isFirst, boolean isLast, + Content linksTree); /** - * Write the inherited member summary footer for the given class. + * Get inherited summary links. * - * @param classDoc the class the summary belongs to. + * @return a content tree conatining the inherited summary links */ - public void writeInheritedMemberSummaryFooter(ClassDoc classDoc); + public Content getInheritedSummaryLinksTree(); + + /** + * Get the member tree. + * + * @param memberTree the content tree representating the member + * @return a content tree for the member + */ + public Content getMemberTree(Content memberTree); /** * Close the writer. diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/MethodWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/MethodWriter.java index e9d2083912d..49fbde09f54 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/MethodWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/MethodWriter.java @@ -36,68 +36,81 @@ import com.sun.javadoc.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public interface MethodWriter { /** - * Write the header for the method documentation. + * Get the method details tree header. * - * @param classDoc the class that the methods belong to. - * @param header the header to write. + * @param classDoc the class being documented + * @param memberDetailsTree the content tree representing member details + * @return content tree for the method details header */ - public void writeHeader(ClassDoc classDoc, String header); + public Content getMethodDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree); /** - * Write the method header for the given method. + * Get the method documentation tree header. * - * @param method the method being documented. - * @param isFirst the flag to indicate whether or not the method is the - * first to be documented. + * @param method the method being documented + * @param methodDetailsTree the content tree representing method details + * @return content tree for the method documentation header */ - public void writeMethodHeader(MethodDoc method, boolean isFirst); + public Content getMethodDocTreeHeader(MethodDoc method, + Content methodDetailsTree); /** - * Write the signature for the given method. + * Get the signature for the given method. * - * @param method the method being documented. + * @param method the method being documented + * @return content tree for the method signature */ - public void writeSignature(MethodDoc method); + public Content getSignature(MethodDoc method); /** - * Write the deprecated output for the given method. + * Add the deprecated output for the given method. * - * @param method the method being documented. + * @param method the method being documented + * @param methodDocTree content tree to which the deprecated information will be added */ - public void writeDeprecated(MethodDoc method); + public void addDeprecated(MethodDoc method, Content methodDocTree); /** - * Write the comments for the given method. + * Add the comments for the given method. * - * @param holder the holder type (not erasure) of the method. - * @param method the method being documented. + * @param holder the holder type (not erasure) of the method + * @param method the method being documented + * @param methodDocTree the content tree to which the comments will be added */ - public void writeComments(Type holder, MethodDoc method); + public void addComments(Type holder, MethodDoc method, Content methodDocTree); /** - * Write the tag output for the given method. + * Add the tags for the given method. * - * @param method the method being documented. + * @param method the method being documented + * @param methodDocTree the content tree to which the tags will be added */ - public void writeTags(MethodDoc method); + public void addTags(MethodDoc method, Content methodDocTree); /** - * Write the method footer. + * Get the method details tree. + * + * @param methodDetailsTree the content tree representing method details + * @return content tree for the method details */ - public void writeMethodFooter(); + public Content getMethodDetails(Content methodDetailsTree); /** - * Write the footer for the method documentation. + * Get the method documentation. * - * @param classDoc the class that the methods belong to. + * @param methodDocTree the content tree representing method documentation + * @param isLastContent true if the content to be added is the last content + * @return content tree for the method documentation */ - public void writeFooter(ClassDoc classDoc); + public Content getMethodDoc(Content methodDocTree, boolean isLastContent); /** * Close the writer. diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/NestedClassWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/NestedClassWriter.java index f11144ad611..07759a71290 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/NestedClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/NestedClassWriter.java @@ -26,7 +26,6 @@ package com.sun.tools.doclets.internal.toolkit; import java.io.*; -import com.sun.javadoc.*; /** * The interface for writing class output. @@ -36,58 +35,12 @@ import com.sun.javadoc.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public interface NestedClassWriter { - /** - * Write the classes summary header for the given class. - * - * @param nestedClass the class the summary belongs to. - */ - public void writeNestedClassSummaryHeader(ClassDoc nestedClass); - - /** - * Write the class summary for the given class and class. - * - * @param classDoc the class the summary belongs to. - * @param nestedClass the nested class that I am summarizing. - */ - public void writeNestedClassSummary(ClassDoc classDoc, ClassDoc nestedClass); - - /** - * Write the classes summary footer for the given class. - * - * @param nestedClass the class the summary belongs to. - */ - public void writeNestedClassSummaryFooter(ClassDoc nestedClass); - - /** - * Write the inherited classes summary header for the given class. - * - * @param nestedClass the class the summary belongs to. - */ - public void writeInheritedNestedClassSummaryHeader(ClassDoc nestedClass); - - /** - * Write the inherited nested class summary for the given class and nested - * class. - * - * @param classDoc the class the inherited nested class belongs to. - * @param nestedClass the inherited nested class that I am summarizing. - * @param isFirst true if this is the first member in the list. - */ - public void writeInheritedNestedClassSummary(ClassDoc classDoc, - ClassDoc nestedClass, boolean isFirst); - - /** - * Write the inherited classes summary footer for the given class. - * - * @param nestedClass the class the summary belongs to. - */ - public void writeInheritedNestedClassSummaryFooter(ClassDoc nestedClass); - /** * Close the writer. */ diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java index 5ffe7b9928e..eb1ad694178 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java @@ -36,6 +36,7 @@ import java.io.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ @@ -49,45 +50,70 @@ public interface PackageSummaryWriter { public abstract String getOutputFileName(); /** - * Write the header for the package summary. + * Get the header for the summary. + * + * @param heading Package name. + * @return the header to be added to the content tree */ - public abstract void writeSummaryHeader(); + public abstract Content getPackageHeader(String heading); /** - * Write the footer for the package summary. + * Get the header for the package content. + * + * @return a content tree for the package content header */ - public abstract void writeSummaryFooter(); + public abstract Content getContentHeader(); /** - * Write the table of classes in this package. + * Get the header for the package summary. + * + * @return a content tree with the package summary header + */ + public abstract Content getSummaryHeader(); + + /** + * Adds the table of classes to the documentation tree. * * @param classes the array of classes to document. * @param label the label for this table. + * @param tableSummary the summary string for the table + * @param tableHeader array of table headers + * @param summaryContentTree the content tree to which the summaries will be added */ - public abstract void writeClassesSummary(ClassDoc[] classes, String label, String tableSummary, String[] tableHeader); + public abstract void addClassesSummary(ClassDoc[] classes, String label, + String tableSummary, String[] tableHeader, Content summaryContentTree); /** - * Write the header for the summary. + * Adds the package description from the "packages.html" file to the documentation + * tree. * - * @param heading Package name. + * @param packageContentTree the content tree to which the package description + * will be added */ - public abstract void writePackageHeader(String heading); + public abstract void addPackageDescription(Content packageContentTree); /** - * Print the package description from the "packages.html" file. - */ - public abstract void writePackageDescription(); - - /** - * Print the tag information from the "packages.html" file. - */ - public abstract void writePackageTags(); - - /** - * Write the footer for the summary. + * Adds the tag information from the "packages.html" file to the documentation + * tree. * + * @param packageContentTree the content tree to which the package tags will + * be added */ - public abstract void writePackageFooter(); + public abstract void addPackageTags(Content packageContentTree); + + /** + * Adds the footer to the documentation tree. + * + * @param contentTree the tree to which the footer will be added + */ + public abstract void addPackageFooter(Content contentTree); + + /** + * Print the package summary document. + * + * @param contentTree the content tree that will be printed + */ + public abstract void printDocument(Content contentTree); /** * Close the writer. diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java index dc19a9bf95a..edcf278f123 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java @@ -43,33 +43,73 @@ import com.sun.javadoc.*; public interface SerializedFormWriter { /** - * Write the given header. + * Get the header. * * @param header the header to write. + * @return the header content tree */ - public void writeHeader(String header); + public Content getHeader(String header); /** - * Write the given package header. + * Get the serialized form summaries header. * - * @param packageName the package header to write. + * @return the serialized form summary header tree */ - public void writePackageHeader(String packageName); + public Content getSerializedSummariesHeader(); /** - * Write the heading for the serializable class. + * Get the package serialized form header. * - * @param classDoc the class being processed. + * @return the package serialized form header tree */ - public void writeClassHeader(ClassDoc classDoc); + public Content getPackageSerializedHeader(); /** - * Write the serial UID info. + * Get the given package header. + * + * @param packageName the package header to write + * @return a content tree for the package header + */ + public Content getPackageHeader(String packageName); + + /** + * Get the serialized class header. + * + * @return a content tree for the serialized class header + */ + public Content getClassSerializedHeader(); + + /** + * Get the heading for the serializable class. + * + * @param classDoc the class being processed + * @return a content tree for the class heading + */ + public Content getClassHeader(ClassDoc classDoc); + + /** + * Get the serial UID info header. + * + * @return a content tree for the serial uid info header + */ + public Content getSerialUIDInfoHeader(); + + /** + * Adds the serial UID info. * * @param header the header that will show up before the UID. * @param serialUID the serial UID to print. + * @param serialUidTree the serial UID tree to which the content will be added. */ - public void writeSerialUIDInfo(String header, String serialUID); + public void addSerialUIDInfo(String header, String serialUID, + Content serialUidTree); + + /** + * Get the class serialize content header. + * + * @return a content tree for the class serialize content header + */ + public Content getClassContentHeader(); /** * Return an instance of a SerialFieldWriter. @@ -91,9 +131,26 @@ public interface SerializedFormWriter { public abstract void close() throws IOException; /** - * Write the footer. + * Get the serialized content. + * + * @param serializedTreeContent content for serialized data + * @return a content tree for serialized information */ - public void writeFooter(); + public Content getSerializedContent(Content serializedTreeContent); + + /** + * Add the footer. + * + * @param serializedTree the serialized tree to be added + */ + public void addFooter(Content serializedTree); + + /** + * Print the serialized form document. + * + * @param serializedTree the content tree that will be printed + */ + public abstract void printDocument(Content serializedTree); /** * Write the serialized form for a given field. @@ -101,56 +158,73 @@ public interface SerializedFormWriter { public interface SerialFieldWriter { /** - * Write the given heading. + * Get the serializable field header. + * + * @return serialized fields header content tree + */ + public Content getSerializableFieldsHeader(); + + /** + * Get the field content header. + * + * @param isLastContent true if this is the last content to be documented + * @return fields header content tree + */ + public Content getFieldsContentHeader(boolean isLastContent); + + /** + * Get the fields content. * * @param heading the heading to write. + * @param contentTree content tree to which the heading will be added + * @return serializable fields content tree */ - public void writeHeader(String heading); + public Content getSerializableFields(String heading, Content contentTree); /** - * Write the deprecated information for this member. + * Adds the deprecated information for this member. * * @param field the field to document. + * @param contentTree content tree to which the deprecated information will be added */ - public void writeMemberDeprecatedInfo(FieldDoc field); + public void addMemberDeprecatedInfo(FieldDoc field, Content contentTree); /** - * Write the description text for this member. + * Adds the description text for this member. * * @param field the field to document. + * @param contentTree content tree to which the member description will be added */ - public void writeMemberDescription(FieldDoc field); + public void addMemberDescription(FieldDoc field, Content contentTree); /** - * Write the description text for this member represented by the tag. + * Adds the description text for this member represented by the tag. * * @param serialFieldTag the field to document (represented by tag). + * @param contentTree content tree to which the member description will be added */ - public void writeMemberDescription(SerialFieldTag serialFieldTag); + public void addMemberDescription(SerialFieldTag serialFieldTag, Content contentTree); /** - * Write the tag information for this member. + * Adds the tag information for this member. * * @param field the field to document. + * @param contentTree content tree to which the member tags will be added */ - public void writeMemberTags(FieldDoc field); + public void addMemberTags(FieldDoc field, Content contentTree); /** - * Write the member header. + * Adds the member header. * * @param fieldType the type of the field. * @param fieldTypeStr the type of the field in string format. We will * print this out if we can't link to the type. * @param fieldDimensions the dimensions of the field. * @param fieldName the name of the field. + * @param contentTree content tree to which the member header will be added */ - public void writeMemberHeader(ClassDoc fieldType, String fieldTypeStr, - String fieldDimensions, String fieldName); - - /** - * Write the member footer. - */ - public void writeMemberFooter(); + public void addMemberHeader(ClassDoc fieldType, String fieldTypeStr, + String fieldDimensions, String fieldName, Content contentTree); /** * Check to see if overview details should be printed. If @@ -162,13 +236,6 @@ public interface SerializedFormWriter { * @return true if overview details need to be printed */ public boolean shouldPrintOverview(FieldDoc field); - - /** - * Write the footer. - * - * @param heading the heading that was written. - */ - public void writeFooter (String heading); } /** @@ -176,45 +243,71 @@ public interface SerializedFormWriter { */ public interface SerialMethodWriter { + /** + * Get the serializable method header. + * + * @return serializable methods content tree + */ + public Content getSerializableMethodsHeader(); + + /** + * Get the method content header. + * + * @param isLastContent true if this is the last content to be documented + * @return methods content tree + */ + public Content getMethodsContentHeader(boolean isLastContent); + /** * Write the given heading. * - * @param heading the heading to write. + * @param heading the heading to write + * @param serializableMethodTree content tree which will be added + * @return serializable methods content tree */ - public void writeHeader(String heading); + public Content getSerializableMethods(String heading, Content serializableMethodTree); /** * Write a warning that no serializable methods exist. * - * @param msg the warning to print. + * @param msg the warning to print + * @return no customization message tree */ - public void writeNoCustomizationMsg(String msg); + public Content getNoCustomizationMsg(String msg); /** - * Write the header. + * Adds the header. * - * @param member the member to write the header for. + * @param member the member to write the header for + * @param methodsContentTree content tree to which the header will be added */ - public void writeMemberHeader(MethodDoc member); + public void addMemberHeader(MethodDoc member, Content methodsContentTree); /** - * Write the footer. + * Adds the deprecated information for this member. + * + * @param member the member to write the deprecated information for + * @param methodsContentTree content tree to which the deprecated + * information will be added */ - public void writeMemberFooter(); + public void addDeprecatedMemberInfo(MethodDoc member, Content methodsContentTree); /** - * Write the deprecated information for this member. + * Adds the description for this member. + * + * @param member the member to write the information for + * @param methodsContentTree content tree to which the member + * information will be added */ - public void writeDeprecatedMemberInfo(MethodDoc member); + public void addMemberDescription(MethodDoc member, Content methodsContentTree); /** - * Write the description for this member. + * Adds the tag information for this member. + * + * @param member the member to write the tags information for + * @param methodsContentTree content tree to which the tags + * information will be added */ - public void writeMemberDescription(MethodDoc member); - - /** - * Write the tag information for this member. - */ - public void writeMemberTags(MethodDoc member); + public void addMemberTags(MethodDoc member, Content methodsContentTree); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java index 4145af7cb90..7730391f963 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java @@ -95,13 +95,14 @@ public abstract class AbstractBuilder { * Build the documentation, as specified by the given XML element. * * @param node the XML element that specifies which component to document. + * @param contentTree content tree to which the documentation will be added */ - protected void build(XMLNode node) { + protected void build(XMLNode node, Content contentTree) { String component = node.name; try { invokeMethod("build" + component, - new Class[] { XMLNode.class }, - new Object[] { node }); + new Class[]{XMLNode.class, Content.class}, + new Object[]{node, contentTree}); } catch (NoSuchMethodException e) { e.printStackTrace(); configuration.root.printError("Unknown element: " + component); @@ -111,8 +112,8 @@ public abstract class AbstractBuilder { } catch (Exception e) { e.printStackTrace(); configuration.root.printError("Exception " + - e.getClass().getName() + - " thrown while processing element: " + component); + e.getClass().getName() + + " thrown while processing element: " + component); throw new DocletAbortException(); } } @@ -121,10 +122,11 @@ public abstract class AbstractBuilder { * Build the documentation, as specified by the children of the given XML element. * * @param node the XML element that specifies which components to document. + * @param contentTree content tree to which the documentation will be added */ - protected void buildChildren(XMLNode node) { - for (XMLNode child: node.children) - build(child); + protected void buildChildren(XMLNode node, Content contentTree) { + for (XMLNode child : node.children) + build(child, contentTree); } /** @@ -140,8 +142,7 @@ public abstract class AbstractBuilder { Object[] params) throws Exception { if (DEBUG) { - configuration.root.printError("DEBUG: " + this.getClass().getName() - + "." + methodName); + configuration.root.printError("DEBUG: " + this.getClass().getName() + "." + methodName); } Method method = this.getClass().getMethod(methodName, paramClasses); method.invoke(this, params); diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractMemberBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractMemberBuilder.java index f91fbd62cc9..a4266c9036f 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractMemberBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractMemberBuilder.java @@ -27,6 +27,7 @@ package com.sun.tools.doclets.internal.toolkit.builders; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; +import java.util.*; /** * The superclass for all member builders. Member builders are only executed @@ -66,12 +67,13 @@ public abstract class AbstractMemberBuilder extends AbstractBuilder { /** * Build the sub component if there is anything to document. * - * @param elements {@inheritDoc} + * @param node the XML element that specifies which components to document. + * @param contentTree content tree to which the documentation will be added */ @Override - public void build(XMLNode node) { + public void build(XMLNode node, Content contentTree) { if (hasMembersToDocument()) { - super.build(node); + super.build(node, contentTree); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java index 8df119853c8..41b8df02d3b 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java @@ -25,11 +25,11 @@ package com.sun.tools.doclets.internal.toolkit.builders; +import java.io.*; +import java.util.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.javadoc.*; -import java.io.*; -import java.util.*; /** * Builds the summary for a given annotation type. @@ -39,6 +39,7 @@ import java.util.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public class AnnotationTypeBuilder extends AbstractBuilder { @@ -58,6 +59,11 @@ public class AnnotationTypeBuilder extends AbstractBuilder { */ private AnnotationTypeWriter writer; + /** + * The content tree for the annotation documentation. + */ + private Content contentTree; + /** * Construct a new ClassBuilder. * @@ -92,7 +98,7 @@ public class AnnotationTypeBuilder extends AbstractBuilder { * {@inheritDoc} */ public void build() throws IOException { - build(LayoutParser.getInstance(configuration).parseXML(ROOT)); + build(LayoutParser.getInstance(configuration).parseXML(ROOT), contentTree); } /** @@ -102,18 +108,24 @@ public class AnnotationTypeBuilder extends AbstractBuilder { return ROOT; } - /** - * Handles the <AnnotationTypeDoc> tag. + /** + * Build the annotation type documentation. * - * @param elements the XML elements that specify how to document a class. + * @param node the XML element that specifies which components to document + * @param contentTree the content tree to which the documentation will be added */ - public void buildAnnotationTypeDoc(XMLNode node) throws Exception { - buildChildren(node); - writer.close(); - copyDocFiles(); + public void buildAnnotationTypeDoc(XMLNode node, Content contentTree) throws Exception { + contentTree = writer.getHeader(configuration.getText("doclet.AnnotationType") + + " " + annotationTypeDoc.name()); + Content annotationContentTree = writer.getAnnotationContentHeader(); + buildChildren(node, annotationContentTree); + contentTree.addContent(annotationContentTree); + writer.addFooter(contentTree); + writer.printDocument(contentTree); + writer.close(); + copyDocFiles(); } - /** * Copy the doc files for the current ClassDoc if necessary. */ @@ -137,86 +149,112 @@ public class AnnotationTypeBuilder extends AbstractBuilder { } /** - * Build the header of the page. + * Build the annotation information tree documentation. + * + * @param node the XML element that specifies which components to document + * @param annotationContentTree the content tree to which the documentation will be added */ - public void buildAnnotationTypeHeader(XMLNode node) { - writer.writeHeader(configuration.getText("doclet.AnnotationType") + - " " + annotationTypeDoc.name()); + public void buildAnnotationTypeInfo(XMLNode node, Content annotationContentTree) { + Content annotationInfoTree = writer.getAnnotationInfoTreeHeader(); + buildChildren(node, annotationInfoTree); + annotationContentTree.addContent(writer.getAnnotationInfo(annotationInfoTree)); } /** - * If this class is deprecated, print the appropriate information. + * If this annotation is deprecated, build the appropriate information. + * + * @param node the XML element that specifies which components to document + * @param annotationInfoTree the content tree to which the documentation will be added */ - public void buildDeprecationInfo (XMLNode node) { - writer.writeAnnotationTypeDeprecationInfo(); + public void buildDeprecationInfo (XMLNode node, Content annotationInfoTree) { + writer.addAnnotationTypeDeprecationInfo(annotationInfoTree); } /** * Build the signature of the current annotation type. - */ - public void buildAnnotationTypeSignature(XMLNode node) { - StringBuffer modifiers = new StringBuffer( - annotationTypeDoc.modifiers() + " "); - writer.writeAnnotationTypeSignature( - Util.replaceText( - modifiers.toString(), "interface", "@interface")); - } - - /** - * Build the class description. - */ - public void buildAnnotationTypeDescription(XMLNode node) { - writer.writeAnnotationTypeDescription(); - } - - /** - * Build the tag information for the current class. - */ - public void buildAnnotationTypeTagInfo(XMLNode node) { - writer.writeAnnotationTypeTagInfo(); - } - - /** - * Build the contents of the page. * - * @param elements the XML elements that specify how a member summary is - * documented. + * @param node the XML element that specifies which components to document + * @param annotationInfoTree the content tree to which the documentation will be added */ - public void buildMemberSummary(XMLNode node) throws Exception { + public void buildAnnotationTypeSignature(XMLNode node, Content annotationInfoTree) { + StringBuffer modifiers = new StringBuffer( + annotationTypeDoc.modifiers() + " "); + writer.addAnnotationTypeSignature(Util.replaceText( + modifiers.toString(), "interface", "@interface"), annotationInfoTree); + } + + /** + * Build the annotation type description. + * + * @param node the XML element that specifies which components to document + * @param annotationInfoTree the content tree to which the documentation will be added + */ + public void buildAnnotationTypeDescription(XMLNode node, Content annotationInfoTree) { + writer.addAnnotationTypeDescription(annotationInfoTree); + } + + /** + * Build the tag information for the current annotation type. + * + * @param node the XML element that specifies which components to document + * @param annotationInfoTree the content tree to which the documentation will be added + */ + public void buildAnnotationTypeTagInfo(XMLNode node, Content annotationInfoTree) { + writer.addAnnotationTypeTagInfo(annotationInfoTree); + } + + /** + * Build the member summary contents of the page. + * + * @param node the XML element that specifies which components to document + * @param annotationContentTree the content tree to which the documentation will be added + */ + public void buildMemberSummary(XMLNode node, Content annotationContentTree) + throws Exception { + Content memberSummaryTree = writer.getMemberTreeHeader(); configuration.getBuilderFactory(). - getMemberSummaryBuilder(writer).buildChildren(node); - writer.completeMemberSummaryBuild(); + getMemberSummaryBuilder(writer).buildChildren(node, memberSummaryTree); + annotationContentTree.addContent(writer.getMemberSummaryTree(memberSummaryTree)); + } + + /** + * Build the member details contents of the page. + * + * @param node the XML element that specifies which components to document + * @param annotationContentTree the content tree to which the documentation will be added + */ + public void buildAnnotationTypeMemberDetails(XMLNode node, Content annotationContentTree) { + Content memberDetailsTree = writer.getMemberTreeHeader(); + buildChildren(node, memberDetailsTree); + if (memberDetailsTree.isValid()) { + Content memberDetails = writer.getMemberTreeHeader(); + writer.addAnnotationDetailsMarker(memberDetails); + memberDetails.addContent(writer.getMemberTree(memberDetailsTree)); + annotationContentTree.addContent(writer.getMemberDetailsTree(memberDetails)); + } } /** * Build the annotation type optional member documentation. * - * @param elements the XML elements that specify how a annotation type - * members are documented. + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added */ - public void buildAnnotationTypeOptionalMemberDetails(XMLNode node) - throws Exception { + public void buildAnnotationTypeOptionalMemberDetails(XMLNode node, Content memberDetailsTree) + throws Exception { configuration.getBuilderFactory(). - getAnnotationTypeOptionalMemberBuilder(writer).buildChildren(node); + getAnnotationTypeOptionalMemberBuilder(writer).buildChildren(node, memberDetailsTree); } /** * Build the annotation type required member documentation. * - * @param elements the XML elements that specify how a annotation type - * members are documented. + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added */ - public void buildAnnotationTypeRequiredMemberDetails(XMLNode node) - throws Exception { + public void buildAnnotationTypeRequiredMemberDetails(XMLNode node, Content memberDetailsTree) + throws Exception { configuration.getBuilderFactory(). - getAnnotationTypeRequiredMemberBuilder(writer).buildChildren(node); - } - - - /** - * Build the footer of the page. - */ - public void buildAnnotationTypeFooter(XMLNode node) { - writer.writeFooter(); + getAnnotationTypeRequiredMemberBuilder(writer).buildChildren(node, memberDetailsTree); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java index 632f26a7ce1..a6253da7dcf 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java @@ -25,11 +25,10 @@ package com.sun.tools.doclets.internal.toolkit.builders; - +import java.util.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.javadoc.*; -import java.util.*; /** * Builds documentation for optional annotation type members. @@ -39,6 +38,7 @@ import java.util.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public class AnnotationTypeOptionalMemberBuilder extends @@ -90,27 +90,25 @@ public class AnnotationTypeOptionalMemberBuilder extends } /** - * Build the member documentation. + * Build the annotation type optional member documentation. * - * @param elements the XML elements that specify how to construct this - * documentation. + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added */ - public void buildAnnotationTypeOptionalMember(XMLNode node) { - if (writer == null) { - return; - } - for (currentMemberIndex = 0; currentMemberIndex < members.size(); - currentMemberIndex++) { - buildChildren(node); - } + public void buildAnnotationTypeOptionalMember(XMLNode node, Content memberDetailsTree) { + buildAnnotationTypeMember(node, memberDetailsTree); } /** - * Document the default value for this optional member. + * Build the default value for this optional member. + * + * @param node the XML element that specifies which components to document + * @param annotationDocTree the content tree to which the documentation will be added */ - public void buildDefaultValueInfo(XMLNode node) { - ((AnnotationTypeOptionalMemberWriter) writer).writeDefaultValueInfo( - (MemberDoc) members.get(currentMemberIndex)); + public void buildDefaultValueInfo(XMLNode node, Content annotationDocTree) { + ((AnnotationTypeOptionalMemberWriter) writer).addDefaultValueInfo( + (MemberDoc) members.get(currentMemberIndex), + annotationDocTree); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java index f278e696b98..d3f0b06b937 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java @@ -25,11 +25,10 @@ package com.sun.tools.doclets.internal.toolkit.builders; - +import java.util.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.javadoc.*; -import java.util.*; /** * Builds documentation for required annotation type members. @@ -39,6 +38,7 @@ import java.util.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder { @@ -140,82 +140,87 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder { return members.size() > 0; } + /** + * Build the annotation type required member documentation. + * + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added + */ + public void buildAnnotationTypeRequiredMember(XMLNode node, Content memberDetailsTree) { + buildAnnotationTypeMember(node, memberDetailsTree); + } + /** * Build the member documentation. * - * @param elements the XML elements that specify how to construct this - * documentation. + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added */ - public void buildAnnotationTypeRequiredMember(XMLNode node) { + public void buildAnnotationTypeMember(XMLNode node, Content memberDetailsTree) { if (writer == null) { return; } - for (currentMemberIndex = 0; currentMemberIndex < members.size(); + int size = members.size(); + if (size > 0) { + writer.addAnnotationDetailsTreeHeader( + classDoc, memberDetailsTree); + for (currentMemberIndex = 0; currentMemberIndex < size; currentMemberIndex++) { - buildChildren(node); + Content annotationDocTree = writer.getAnnotationDocTreeHeader( + (MemberDoc) members.get(currentMemberIndex), + memberDetailsTree); + buildChildren(node, annotationDocTree); + memberDetailsTree.addContent(writer.getAnnotationDoc( + annotationDocTree, (currentMemberIndex == size - 1))); + } } } - /** - * Build the overall header. - */ - public void buildHeader(XMLNode node) { - writer.writeHeader(classDoc, - configuration.getText("doclet.Annotation_Type_Member_Detail")); - } - - /** - * Build the header for the individual members. - */ - public void buildMemberHeader(XMLNode node) { - writer.writeMemberHeader((MemberDoc) members.get( - currentMemberIndex), - currentMemberIndex == 0); - } - /** * Build the signature. + * + * @param node the XML element that specifies which components to document + * @param annotationDocTree the content tree to which the documentation will be added */ - public void buildSignature(XMLNode node) { - writer.writeSignature((MemberDoc) members.get(currentMemberIndex)); + public void buildSignature(XMLNode node, Content annotationDocTree) { + annotationDocTree.addContent( + writer.getSignature((MemberDoc) members.get(currentMemberIndex))); } /** * Build the deprecation information. + * + * @param node the XML element that specifies which components to document + * @param annotationDocTree the content tree to which the documentation will be added */ - public void buildDeprecationInfo(XMLNode node) { - writer.writeDeprecated((MemberDoc) members.get(currentMemberIndex)); + public void buildDeprecationInfo(XMLNode node, Content annotationDocTree) { + writer.addDeprecated((MemberDoc) members.get(currentMemberIndex), + annotationDocTree); } /** * Build the comments for the member. Do nothing if * {@link Configuration#nocomment} is set to true. + * + * @param node the XML element that specifies which components to document + * @param annotationDocTree the content tree to which the documentation will be added */ - public void buildMemberComments(XMLNode node) { + public void buildMemberComments(XMLNode node, Content annotationDocTree) { if(! configuration.nocomment){ - writer.writeComments((MemberDoc) members.get(currentMemberIndex)); + writer.addComments((MemberDoc) members.get(currentMemberIndex), + annotationDocTree); } } /** * Build the tag information. + * + * @param node the XML element that specifies which components to document + * @param annotationDocTree the content tree to which the documentation will be added */ - public void buildTagInfo(XMLNode node) { - writer.writeTags((MemberDoc) members.get(currentMemberIndex)); - } - - /** - * Build the footer for the individual member. - */ - public void buildMemberFooter(XMLNode node) { - writer.writeMemberFooter(); - } - - /** - * Build the overall footer. - */ - public void buildFooter(XMLNode node) { - writer.writeFooter(classDoc); + public void buildTagInfo(XMLNode node, Content annotationDocTree) { + writer.addTags((MemberDoc) members.get(currentMemberIndex), + annotationDocTree); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java index 15a5341d8d1..3e10f007089 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ClassBuilder.java @@ -25,11 +25,11 @@ package com.sun.tools.doclets.internal.toolkit.builders; +import java.io.*; +import java.util.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.javadoc.*; -import java.io.*; -import java.util.*; /** * Builds the summary for a given class. @@ -39,6 +39,7 @@ import java.util.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public class ClassBuilder extends AbstractBuilder { @@ -68,6 +69,11 @@ public class ClassBuilder extends AbstractBuilder { */ private boolean isEnum = false; + /** + * The content tree for the class documentation. + */ + private Content contentTree; + /** * Construct a new ClassBuilder. * @@ -108,7 +114,7 @@ public class ClassBuilder extends AbstractBuilder { * {@inheritDoc} */ public void build() throws IOException { - build(LayoutParser.getInstance(configuration).parseXML(ROOT)); + build(LayoutParser.getInstance(configuration).parseXML(ROOT), contentTree); } /** @@ -121,121 +127,159 @@ public class ClassBuilder extends AbstractBuilder { /** * Handles the <ClassDoc> tag. * - * @param elements the XML elements that specify how to document a class. + * @param node the XML element that specifies which components to document + * @param contentTree the content tree to which the documentation will be added */ - public void buildClassDoc(XMLNode node) throws Exception { - buildChildren(node); - writer.close(); - copyDocFiles(); + public void buildClassDoc(XMLNode node, Content contentTree) throws Exception { + String key; + if (isInterface) { + key = "doclet.Interface"; + } else if (isEnum) { + key = "doclet.Enum"; + } else { + key = "doclet.Class"; + } + contentTree = writer.getHeader(configuration.getText(key) + " " + + classDoc.name()); + Content classContentTree = writer.getClassContentHeader(); + buildChildren(node, classContentTree); + contentTree.addContent(classContentTree); + writer.addFooter(contentTree); + writer.printDocument(contentTree); + writer.close(); + copyDocFiles(); } - /** - * Copy the doc files for the current ClassDoc if necessary. + * Build the class tree documentation. + * + * @param node the XML element that specifies which components to document + * @param classContentTree the content tree to which the documentation will be added */ + public void buildClassTree(XMLNode node, Content classContentTree) { + writer.addClassTree(classContentTree); + } + + /** + * Build the class information tree documentation. + * + * @param node the XML element that specifies which components to document + * @param classContentTree the content tree to which the documentation will be added + */ + public void buildClassInfo(XMLNode node, Content classContentTree) { + Content classInfoTree = writer.getClassInfoTreeHeader(); + buildChildren(node, classInfoTree); + classContentTree.addContent(writer.getClassInfo(classInfoTree)); + } + + /** + * Build the typeparameters of this class. + * + * @param node the XML element that specifies which components to document + * @param classInfoTree the content tree to which the documentation will be added + */ + public void buildTypeParamInfo(XMLNode node, Content classInfoTree) { + writer.addTypeParamInfo(classInfoTree); + } + + /** + * If this is an interface, list all super interfaces. + * + * @param node the XML element that specifies which components to document + * @param classInfoTree the content tree to which the documentation will be added + */ + public void buildSuperInterfacesInfo(XMLNode node, Content classInfoTree) { + writer.addSuperInterfacesInfo(classInfoTree); + } + + /** + * If this is a class, list all interfaces implemented by this class. + * + * @param node the XML element that specifies which components to document + * @param classInfoTree the content tree to which the documentation will be added + */ + public void buildImplementedInterfacesInfo(XMLNode node, Content classInfoTree) { + writer.addImplementedInterfacesInfo(classInfoTree); + } + + /** + * List all the classes extend this one. + * + * @param node the XML element that specifies which components to document + * @param classInfoTree the content tree to which the documentation will be added + */ + public void buildSubClassInfo(XMLNode node, Content classInfoTree) { + writer.addSubClassInfo(classInfoTree); + } + + /** + * List all the interfaces that extend this one. + * + * @param node the XML element that specifies which components to document + * @param classInfoTree the content tree to which the documentation will be added + */ + public void buildSubInterfacesInfo(XMLNode node, Content classInfoTree) { + writer.addSubInterfacesInfo(classInfoTree); + } + + /** + * If this is an interface, list all classes that implement this interface. + * + * @param node the XML element that specifies which components to document + * @param classInfoTree the content tree to which the documentation will be added + */ + public void buildInterfaceUsageInfo(XMLNode node, Content classInfoTree) { + writer.addInterfaceUsageInfo(classInfoTree); + } + + /** + * If this class is deprecated, build the appropriate information. + * + * @param node the XML element that specifies which components to document + * @param classInfoTree the content tree to which the documentation will be added + */ + public void buildDeprecationInfo (XMLNode node, Content classInfoTree) { + writer.addClassDeprecationInfo(classInfoTree); + } + + /** + * If this is an inner class or interface, list the enclosing class or interface. + * + * @param node the XML element that specifies which components to document + * @param classInfoTree the content tree to which the documentation will be added + */ + public void buildNestedClassInfo (XMLNode node, Content classInfoTree) { + writer.addNestedClassInfo(classInfoTree); + } + + /** + * Copy the doc files for the current ClassDoc if necessary. + */ private void copyDocFiles() { PackageDoc containingPackage = classDoc.containingPackage(); if((configuration.packages == null || Arrays.binarySearch(configuration.packages, - containingPackage) < 0) && - ! containingPackagesSeen.contains(containingPackage.name())){ + containingPackage) < 0) && + ! containingPackagesSeen.contains(containingPackage.name())){ //Only copy doc files dir if the containing package is not //documented AND if we have not documented a class from the same //package already. Otherwise, we are making duplicate copies. Util.copyDocFiles(configuration, - Util.getPackageSourcePath(configuration, + Util.getPackageSourcePath(configuration, classDoc.containingPackage()) + - DirectoryManager.getDirectoryPath(classDoc.containingPackage()) + DirectoryManager.getDirectoryPath(classDoc.containingPackage()) + File.separator, DocletConstants.DOC_FILES_DIR_NAME, true); containingPackagesSeen.add(containingPackage.name()); } } - /** - * Build the header of the page. - */ - public void buildClassHeader(XMLNode node) { - String key; - if (isInterface) { - key = "doclet.Interface"; - } else if (isEnum) { - key = "doclet.Enum"; - } else { - key = "doclet.Class"; - } - - writer.writeHeader(configuration.getText(key) + " " + classDoc.name()); - } - - /** - * Build the class tree documentation. - */ - public void buildClassTree(XMLNode node) { - writer.writeClassTree(); - } - - /** - * If this is a class, list all interfaces - * implemented by this class. - */ - public void buildImplementedInterfacesInfo(XMLNode node) { - writer.writeImplementedInterfacesInfo(); - } - - /** - * If this is an interface, list all super interfaces. - */ - public void buildSuperInterfacesInfo(XMLNode node) { - writer.writeSuperInterfacesInfo(); - } - - /** - * List the parameters of this class. - */ - public void buildTypeParamInfo(XMLNode node) { - writer.writeTypeParamInfo(); - } - - /** - * List all the classes extend this one. - */ - public void buildSubClassInfo(XMLNode node) { - writer.writeSubClassInfo(); - } - - /** - * List all the interfaces that extend this one. - */ - public void buildSubInterfacesInfo(XMLNode node) { - writer.writeSubInterfacesInfo(); - } - - /** - * If this is an interface, list all classes that implement this interface. - */ - public void buildInterfaceUsageInfo (XMLNode node) { - writer.writeInterfaceUsageInfo(); - } - - /** - * If this is an inner class or interface, list the enclosing class or - * interface. - */ - public void buildNestedClassInfo (XMLNode node) { - writer.writeNestedClassInfo(); - } - - /** - * If this class is deprecated, print the appropriate information. - */ - public void buildDeprecationInfo (XMLNode node) { - writer.writeClassDeprecationInfo(); - } - /** * Build the signature of the current class. + * + * @param node the XML element that specifies which components to document + * @param classInfoTree the content tree to which the documentation will be added */ - public void buildClassSignature(XMLNode node) { + public void buildClassSignature(XMLNode node, Content classInfoTree) { StringBuffer modifiers = new StringBuffer(classDoc.modifiers() + " "); if (isEnum) { modifiers.append("enum "); @@ -243,93 +287,111 @@ public class ClassBuilder extends AbstractBuilder { if ((index = modifiers.indexOf("abstract")) >= 0) { modifiers.delete(index, index + (new String("abstract")).length()); modifiers = new StringBuffer( - Util.replaceText(modifiers.toString(), " ", " ")); + Util.replaceText(modifiers.toString(), " ", " ")); } if ((index = modifiers.indexOf("final")) >= 0) { modifiers.delete(index, index + (new String("final")).length()); modifiers = new StringBuffer( - Util.replaceText(modifiers.toString(), " ", " ")); + Util.replaceText(modifiers.toString(), " ", " ")); } //} else if (classDoc.isAnnotationType()) { //modifiers.append("@interface "); } else if (! isInterface) { modifiers.append("class "); } - writer.writeClassSignature(modifiers.toString()); + writer.addClassSignature(modifiers.toString(), classInfoTree); } /** * Build the class description. + * + * @param node the XML element that specifies which components to document + * @param classInfoTree the content tree to which the documentation will be added */ - public void buildClassDescription(XMLNode node) { - writer.writeClassDescription(); + public void buildClassDescription(XMLNode node, Content classInfoTree) { + writer.addClassDescription(classInfoTree); } /** * Build the tag information for the current class. + * + * @param node the XML element that specifies which components to document + * @param classInfoTree the content tree to which the documentation will be added */ - public void buildClassTagInfo(XMLNode node) { - writer.writeClassTagInfo(); + public void buildClassTagInfo(XMLNode node, Content classInfoTree) { + writer.addClassTagInfo(classInfoTree); } /** - * Build the contents of the page. + * Build the member summary contents of the page. * - * @param elements the XML elements that specify how a member summary is - * documented. + * @param node the XML element that specifies which components to document + * @param classContentTree the content tree to which the documentation will be added */ - public void buildMemberSummary(XMLNode node) throws Exception { + public void buildMemberSummary(XMLNode node, Content classContentTree) throws Exception { + Content memberSummaryTree = writer.getMemberTreeHeader(); configuration.getBuilderFactory(). - getMemberSummaryBuilder(writer).buildChildren(node); - writer.completeMemberSummaryBuild(); + getMemberSummaryBuilder(writer).buildChildren(node, memberSummaryTree); + classContentTree.addContent(writer.getMemberSummaryTree(memberSummaryTree)); + } + + /** + * Build the member details contents of the page. + * + * @param node the XML element that specifies which components to document + * @param classContentTree the content tree to which the documentation will be added + */ + public void buildMemberDetails(XMLNode node, Content classContentTree) { + Content memberDetailsTree = writer.getMemberTreeHeader(); + buildChildren(node, memberDetailsTree); + classContentTree.addContent(writer.getMemberDetailsTree(memberDetailsTree)); } /** * Build the enum constants documentation. * - * @param elements the XML elements that specify how a enum constants are - * documented. + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added */ - public void buildEnumConstantsDetails(XMLNode node) throws Exception { + public void buildEnumConstantsDetails(XMLNode node, + Content memberDetailsTree) throws Exception { configuration.getBuilderFactory(). - getEnumConstantsBuilder(writer).buildChildren(node); + getEnumConstantsBuilder(writer).buildChildren(node, memberDetailsTree); } /** * Build the field documentation. * - * @param elements the XML elements that specify how a field is documented. + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added */ - public void buildFieldDetails(XMLNode node) throws Exception { + public void buildFieldDetails(XMLNode node, + Content memberDetailsTree) throws Exception { configuration.getBuilderFactory(). - getFieldBuilder(writer).buildChildren(node); + getFieldBuilder(writer).buildChildren(node, memberDetailsTree); } /** * Build the constructor documentation. * - * @param elements the XML elements that specify how to document a - * constructor. + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added */ - public void buildConstructorDetails(XMLNode node) throws Exception { + public void buildConstructorDetails(XMLNode node, + Content memberDetailsTree) throws Exception { configuration.getBuilderFactory(). - getConstructorBuilder(writer).buildChildren(node); + getConstructorBuilder(writer).buildChildren(node, memberDetailsTree); } /** * Build the method documentation. * - * @param elements the XML elements that specify how a method is documented. + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added */ - public void buildMethodDetails(XMLNode node) throws Exception { + public void buildMethodDetails(XMLNode node, + Content memberDetailsTree) throws Exception { configuration.getBuilderFactory(). - getMethodBuilder(writer).buildChildren(node); - } - - /** - * Build the footer of the page. - */ - public void buildClassFooter(XMLNode node) { - writer.writeFooter(); + getMethodBuilder(writer).buildChildren(node, memberDetailsTree); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstantsSummaryBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstantsSummaryBuilder.java index 2126b619ba7..0b16a57bcd8 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstantsSummaryBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstantsSummaryBuilder.java @@ -25,11 +25,11 @@ package com.sun.tools.doclets.internal.toolkit.builders; -import com.sun.tools.doclets.internal.toolkit.util.*; -import com.sun.tools.doclets.internal.toolkit.*; -import com.sun.javadoc.*; import java.io.*; import java.util.*; +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.internal.toolkit.*; /** * Builds the Constants Summary Page. @@ -39,6 +39,7 @@ import java.util.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public class ConstantsSummaryBuilder extends AbstractBuilder { @@ -79,6 +80,11 @@ public class ConstantsSummaryBuilder extends AbstractBuilder { */ private ClassDoc currentClass; + /** + * The content tree for the constant summary documentation. + */ + private Content contentTree; + /** * Construct a new ConstantsSummaryBuilder. * @@ -113,7 +119,7 @@ public class ConstantsSummaryBuilder extends AbstractBuilder { //Doclet does not support this output. return; } - build(LayoutParser.getInstance(configuration).parseXML(ROOT)); + build(LayoutParser.getInstance(configuration).parseXML(ROOT), contentTree); } /** @@ -126,85 +132,85 @@ public class ConstantsSummaryBuilder extends AbstractBuilder { /** * Build the constant summary. * - * @param elements the list of elements describing constant summary - * documentation. + * @param node the XML element that specifies which components to document + * @param contentTree the content tree to which the documentation will be added */ - public void buildConstantSummary(XMLNode node) throws Exception { - buildChildren(node); + public void buildConstantSummary(XMLNode node, Content contentTree) throws Exception { + contentTree = writer.getHeader(); + buildChildren(node, contentTree); + writer.addFooter(contentTree); + writer.printDocument(contentTree); writer.close(); } /** - * Build the header. + * Build the list of packages. + * + * @param node the XML element that specifies which components to document + * @param contentTree the content tree to which the content list will be added */ - public void buildHeader(XMLNode node) { - writer.writeHeader(); - } - - /** - * Build the footer. - */ - public void buildFooter(XMLNode node) { - writer.writeFooter(); - } - - /** - * Build the table of contents. - */ - public void buildContents(XMLNode node) { - writer.writeContentsHeader(); + public void buildContents(XMLNode node, Content contentTree) { + Content contentListTree = writer.getContentsHeader(); PackageDoc[] packages = configuration.packages; printedPackageHeaders = new HashSet(); for (int i = 0; i < packages.length; i++) { if (hasConstantField(packages[i]) && ! hasPrintedPackageIndex(packages[i].name())) { - writer.writeLinkToPackageContent(packages[i], + writer.addLinkToPackageContent(packages[i], parsePackageName(packages[i].name()), - printedPackageHeaders); + printedPackageHeaders, contentListTree); } } - writer.writeContentsFooter(); + contentTree.addContent(writer.getContentsList(contentListTree)); } /** * Build the summary for each documented package. * - * @param elements the XML elements that represent the components - * of documentation for each package. + * @param node the XML element that specifies which components to document + * @param contentTree the tree to which the summaries will be added */ - public void buildConstantSummaries(XMLNode node) { + public void buildConstantSummaries(XMLNode node, Content contentTree) { PackageDoc[] packages = configuration.packages; printedPackageHeaders = new HashSet(); + Content summariesTree = writer.getConstantSummaries(); for (int i = 0; i < packages.length; i++) { if (hasConstantField(packages[i])) { currentPackage = packages[i]; //Build the documentation for the current package. - buildChildren(node); + buildChildren(node, summariesTree); } } + contentTree.addContent(summariesTree); } /** - * Build the summary for the current package. + * Build the header for the given package. * - * @param elements the list of XML elements that make up package - * documentation. + * @param node the XML element that specifies which components to document + * @param summariesTree the tree to which the package header will be added */ - public void buildPackageConstantSummary(XMLNode node) { - buildChildren(node); + public void buildPackageHeader(XMLNode node, Content summariesTree) { + String parsedPackageName = parsePackageName(currentPackage.name()); + if (! printedPackageHeaders.contains(parsedPackageName)) { + writer.addPackageName(currentPackage, + parsePackageName(currentPackage.name()), summariesTree); + printedPackageHeaders.add(parsedPackageName); + } } /** * Build the summary for the current class. * - * @param elements the list of XML elements that make up the class - * constant summary. + * @param node the XML element that specifies which components to document + * @param summariesTree the tree to which the class constant summary will be added */ - public void buildClassConstantSummary(XMLNode node) { + public void buildClassConstantSummary(XMLNode node, Content summariesTree) { ClassDoc[] classes = currentPackage.name().length() > 0 ? currentPackage.allClasses() : configuration.classDocCatalog.allClasses( DocletConstants.DEFAULT_PACKAGE_NAME); Arrays.sort(classes); + Content classConstantTree = writer.getClassConstantHeader(); for (int i = 0; i < classes.length; i++) { if (! classDocsWithConstFields.contains(classes[i]) || ! classes[i].isIncluded()) { @@ -212,42 +218,20 @@ public class ConstantsSummaryBuilder extends AbstractBuilder { } currentClass = classes[i]; //Build the documentation for the current class. - buildChildren(node); + buildChildren(node, classConstantTree); } + summariesTree.addContent(classConstantTree); } /** - * Build the header for the given class. + * Build the summary of constant members in the class. + * + * @param node the XML element that specifies which components to document + * @param classConstantTree the tree to which the constant members table + * will be added */ - public void buildPackageHeader(XMLNode node) { - String parsedPackageName = parsePackageName(currentPackage.name()); - if (! printedPackageHeaders.contains(parsedPackageName)) { - writer.writePackageName(currentPackage, - parsePackageName(currentPackage.name())); - printedPackageHeaders.add(parsedPackageName); - } - } - - /** - * Build the header for the given class. - */ - public void buildClassHeader(XMLNode node) { - writer.writeConstantMembersHeader(currentClass); - } - - /** - * Print summary of constant members in the - * class. - */ - public void buildConstantMembers(XMLNode node) { - new ConstantFieldBuilder(currentClass).buildMembersSummary(node); - } - - /** - * Build the footer for the given class. - */ - public void buildClassFooter(XMLNode node) { - writer.writeConstantMembersFooter(currentClass); + public void buildConstantMembers(XMLNode node, Content classConstantTree) { + new ConstantFieldBuilder(currentClass).buildMembersSummary(node, classConstantTree); } /** @@ -346,12 +330,16 @@ public class ConstantsSummaryBuilder extends AbstractBuilder { /** * Builds the table of constants for a given class. + * + * @param node the XML element that specifies which components to document + * @param classConstantTree the tree to which the class constants table + * will be added */ - protected void buildMembersSummary(XMLNode node) { + protected void buildMembersSummary(XMLNode node, Content classConstantTree) { List members = new ArrayList(members()); if (members.size() > 0) { Collections.sort(members); - writer.writeConstantMembers(classdoc, members); + writer.addConstantMembers(classdoc, members, classConstantTree); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstructorBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstructorBuilder.java index ea3b3bee97c..53957ccb9af 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstructorBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ConstructorBuilder.java @@ -25,10 +25,10 @@ package com.sun.tools.doclets.internal.toolkit.builders; +import java.util.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.javadoc.*; -import java.util.*; /** * Builds documentation for a constructor. @@ -38,200 +38,195 @@ import java.util.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public class ConstructorBuilder extends AbstractMemberBuilder { - /** - * The name of this builder. - */ - public static final String NAME = "ConstructorDetails"; + /** + * The name of this builder. + */ + public static final String NAME = "ConstructorDetails"; - /** - * The index of the current field that is being documented at this point - * in time. - */ - private int currentMethodIndex; + /** + * The index of the current field that is being documented at this point + * in time. + */ + private int currentConstructorIndex; - /** - * The class whose constructors are being documented. - */ - private ClassDoc classDoc; + /** + * The class whose constructors are being documented. + */ + private ClassDoc classDoc; - /** - * The visible constructors for the given class. - */ - private VisibleMemberMap visibleMemberMap; + /** + * The visible constructors for the given class. + */ + private VisibleMemberMap visibleMemberMap; - /** - * The writer to output the constructor documentation. - */ - private ConstructorWriter writer; + /** + * The writer to output the constructor documentation. + */ + private ConstructorWriter writer; - /** - * The constructors being documented. - */ - private List constructors; + /** + * The constructors being documented. + */ + private List constructors; - /** - * Construct a new ConstructorBuilder. - * - * @param configuration the current configuration of the - * doclet. - */ - private ConstructorBuilder(Configuration configuration) { - super(configuration); + /** + * Construct a new ConstructorBuilder. + * + * @param configuration the current configuration of the + * doclet. + */ + private ConstructorBuilder(Configuration configuration) { + super(configuration); + } + + /** + * Construct a new ConstructorBuilder. + * + * @param configuration the current configuration of the doclet. + * @param classDoc the class whoses members are being documented. + * @param writer the doclet specific writer. + */ + public static ConstructorBuilder getInstance( + Configuration configuration, + ClassDoc classDoc, + ConstructorWriter writer) { + ConstructorBuilder builder = new ConstructorBuilder(configuration); + builder.classDoc = classDoc; + builder.writer = writer; + builder.visibleMemberMap = + new VisibleMemberMap( + classDoc, + VisibleMemberMap.CONSTRUCTORS, + configuration.nodeprecated); + builder.constructors = + new ArrayList(builder.visibleMemberMap.getMembersFor(classDoc)); + for (int i = 0; i < builder.constructors.size(); i++) { + if (builder.constructors.get(i).isProtected() + || builder.constructors.get(i).isPrivate()) { + writer.setFoundNonPubConstructor(true); + } } - - /** - * Construct a new ConstructorBuilder. - * - * @param configuration the current configuration of the doclet. - * @param classDoc the class whoses members are being documented. - * @param writer the doclet specific writer. - */ - public static ConstructorBuilder getInstance( - Configuration configuration, - ClassDoc classDoc, - ConstructorWriter writer) { - ConstructorBuilder builder = new ConstructorBuilder(configuration); - builder.classDoc = classDoc; - builder.writer = writer; - builder.visibleMemberMap = - new VisibleMemberMap( - classDoc, - VisibleMemberMap.CONSTRUCTORS, - configuration.nodeprecated); - builder.constructors = - new ArrayList(builder.visibleMemberMap.getMembersFor(classDoc)); - for (int i = 0; i < builder.constructors.size(); i++) { - if (builder.constructors.get(i).isProtected() - || builder.constructors.get(i).isPrivate()) { - writer.setFoundNonPubConstructor(true); - } - } - if (configuration.getMemberComparator() != null) { - Collections.sort( - builder.constructors, - configuration.getMemberComparator()); - } - return builder; + if (configuration.getMemberComparator() != null) { + Collections.sort( + builder.constructors, + configuration.getMemberComparator()); } + return builder; + } - /** - * {@inheritDoc} - */ - public String getName() { - return NAME; - } + /** + * {@inheritDoc} + */ + public String getName() { + return NAME; + } - /** - * {@inheritDoc} - */ - public boolean hasMembersToDocument() { - return constructors.size() > 0; - } + /** + * {@inheritDoc} + */ + public boolean hasMembersToDocument() { + return constructors.size() > 0; + } - /** - * Returns a list of constructors that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @return a list of constructors that will be documented. - */ - public List members(ClassDoc classDoc) { - return visibleMemberMap.getMembersFor(classDoc); - } + /** + * Returns a list of constructors that will be documented for the given class. + * This information can be used for doclet specific documentation + * generation. + * + * @return a list of constructors that will be documented. + */ + public List members(ClassDoc classDoc) { + return visibleMemberMap.getMembersFor(classDoc); + } - /** - * Return the constructor writer for this builder. - * - * @return the constructor writer for this builder. - */ - public ConstructorWriter getWriter() { - return writer; - } + /** + * Return the constructor writer for this builder. + * + * @return the constructor writer for this builder. + */ + public ConstructorWriter getWriter() { + return writer; + } - /** - * Build the constructor documentation. - * - * @param elements the XML elements that specify how to construct this - * documentation. - */ - public void buildConstructorDoc(XMLNode node) { - if (writer == null) { - return; - } - for (currentMethodIndex = 0; - currentMethodIndex < constructors.size(); - currentMethodIndex++) { - buildChildren(node); - } + /** + * Build the constructor documentation. + * + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added + */ + public void buildConstructorDoc(XMLNode node, Content memberDetailsTree) { + if (writer == null) { + return; } + int size = constructors.size(); + if (size > 0) { + Content constructorDetailsTree = writer.getConstructorDetailsTreeHeader( + classDoc, memberDetailsTree); + for (currentConstructorIndex = 0; currentConstructorIndex < size; + currentConstructorIndex++) { + Content constructorDocTree = writer.getConstructorDocTreeHeader( + (ConstructorDoc) constructors.get(currentConstructorIndex), + constructorDetailsTree); + buildChildren(node, constructorDocTree); + constructorDetailsTree.addContent(writer.getConstructorDoc( + constructorDocTree, (currentConstructorIndex == size - 1))); + } + memberDetailsTree.addContent( + writer.getConstructorDetails(constructorDetailsTree)); + } + } - /** - * Build the overall header. - */ - public void buildHeader(XMLNode node) { - writer.writeHeader( - classDoc, - configuration.getText("doclet.Constructor_Detail")); - } + /** + * Build the signature. + * + * @param node the XML element that specifies which components to document + * @param constructorDocTree the content tree to which the documentation will be added + */ + public void buildSignature(XMLNode node, Content constructorDocTree) { + constructorDocTree.addContent( + writer.getSignature( + (ConstructorDoc) constructors.get(currentConstructorIndex))); + } - /** - * Build the header for the individual constructor. - */ - public void buildConstructorHeader(XMLNode node) { - writer.writeConstructorHeader( - (ConstructorDoc) constructors.get(currentMethodIndex), - currentMethodIndex == 0); - } + /** + * Build the deprecation information. + * + * @param node the XML element that specifies which components to document + * @param constructorDocTree the content tree to which the documentation will be added + */ + public void buildDeprecationInfo(XMLNode node, Content constructorDocTree) { + writer.addDeprecated( + (ConstructorDoc) constructors.get(currentConstructorIndex), constructorDocTree); + } - /** - * Build the signature. - */ - public void buildSignature(XMLNode node) { - writer.writeSignature( - (ConstructorDoc) constructors.get(currentMethodIndex)); + /** + * Build the comments for the constructor. Do nothing if + * {@link Configuration#nocomment} is set to true. + * + * @param node the XML element that specifies which components to document + * @param constructorDocTree the content tree to which the documentation will be added + */ + public void buildConstructorComments(XMLNode node, Content constructorDocTree) { + if (!configuration.nocomment) { + writer.addComments( + (ConstructorDoc) constructors.get(currentConstructorIndex), + constructorDocTree); } + } - /** - * Build the deprecation information. - */ - public void buildDeprecationInfo(XMLNode node) { - writer.writeDeprecated( - (ConstructorDoc) constructors.get(currentMethodIndex)); - } - - /** - * Build the comments for the constructor. Do nothing if - * {@link Configuration#nocomment} is set to true. - */ - public void buildConstructorComments(XMLNode node) { - if (!configuration.nocomment) { - writer.writeComments( - (ConstructorDoc) constructors.get(currentMethodIndex)); - } - } - - /** - * Build the tag information. - */ - public void buildTagInfo(XMLNode node) { - writer.writeTags((ConstructorDoc) constructors.get(currentMethodIndex)); - } - - /** - * Build the footer for the individual constructor. - */ - public void buildConstructorFooter(XMLNode node) { - writer.writeConstructorFooter(); - } - - /** - * Build the overall footer. - */ - public void buildFooter(XMLNode node) { - writer.writeFooter(classDoc); - } + /** + * Build the tag information. + * + * @param node the XML element that specifies which components to document + * @param constructorDocTree the content tree to which the documentation will be added + */ + public void buildTagInfo(XMLNode node, Content constructorDocTree) { + writer.addTags((ConstructorDoc) constructors.get(currentConstructorIndex), + constructorDocTree); + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/EnumConstantBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/EnumConstantBuilder.java index f0cff8374b5..c390ea6d670 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/EnumConstantBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/EnumConstantBuilder.java @@ -25,10 +25,10 @@ package com.sun.tools.doclets.internal.toolkit.builders; +import java.util.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.javadoc.*; -import java.util.*; /** * Builds documentation for a enum constants. @@ -38,200 +38,195 @@ import java.util.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public class EnumConstantBuilder extends AbstractMemberBuilder { - /** - * The class whose enum constants are being documented. - */ - private ClassDoc classDoc; + /** + * The class whose enum constants are being documented. + */ + private ClassDoc classDoc; - /** - * The visible enum constantss for the given class. - */ - private VisibleMemberMap visibleMemberMap; + /** + * The visible enum constantss for the given class. + */ + private VisibleMemberMap visibleMemberMap; - /** - * The writer to output the enum constants documentation. - */ - private EnumConstantWriter writer; + /** + * The writer to output the enum constants documentation. + */ + private EnumConstantWriter writer; - /** - * The list of enum constants being documented. - */ - private List enumConstants; + /** + * The list of enum constants being documented. + */ + private List enumConstants; - /** - * The index of the current enum constant that is being documented at this point - * in time. - */ - private int currentEnumConstantsIndex; + /** + * The index of the current enum constant that is being documented at this point + * in time. + */ + private int currentEnumConstantsIndex; - /** - * Construct a new EnumConstantsBuilder. - * - * @param configuration the current configuration of the - * doclet. - */ - private EnumConstantBuilder(Configuration configuration) { - super(configuration); + /** + * Construct a new EnumConstantsBuilder. + * + * @param configuration the current configuration of the + * doclet. + */ + private EnumConstantBuilder(Configuration configuration) { + super(configuration); + } + + /** + * Construct a new EnumConstantsBuilder. + * + * @param configuration the current configuration of the doclet. + * @param classDoc the class whoses members are being documented. + * @param writer the doclet specific writer. + */ + public static EnumConstantBuilder getInstance( + Configuration configuration, + ClassDoc classDoc, + EnumConstantWriter writer) { + EnumConstantBuilder builder = new EnumConstantBuilder(configuration); + builder.classDoc = classDoc; + builder.writer = writer; + builder.visibleMemberMap = + new VisibleMemberMap( + classDoc, + VisibleMemberMap.ENUM_CONSTANTS, + configuration.nodeprecated); + builder.enumConstants = + new ArrayList(builder.visibleMemberMap.getMembersFor(classDoc)); + if (configuration.getMemberComparator() != null) { + Collections.sort( + builder.enumConstants, + configuration.getMemberComparator()); } + return builder; + } - /** - * Construct a new EnumConstantsBuilder. - * - * @param configuration the current configuration of the doclet. - * @param classDoc the class whoses members are being documented. - * @param writer the doclet specific writer. - */ - public static EnumConstantBuilder getInstance( - Configuration configuration, - ClassDoc classDoc, - EnumConstantWriter writer) { - EnumConstantBuilder builder = new EnumConstantBuilder(configuration); - builder.classDoc = classDoc; - builder.writer = writer; - builder.visibleMemberMap = - new VisibleMemberMap( - classDoc, - VisibleMemberMap.ENUM_CONSTANTS, - configuration.nodeprecated); - builder.enumConstants = - new ArrayList(builder.visibleMemberMap.getMembersFor(classDoc)); - if (configuration.getMemberComparator() != null) { - Collections.sort( - builder.enumConstants, - configuration.getMemberComparator()); - } - return builder; + /** + * {@inheritDoc} + */ + public String getName() { + return "EnumConstantDetails"; + } + + /** + * Returns a list of enum constants that will be documented for the given class. + * This information can be used for doclet specific documentation + * generation. + * + * @param classDoc the {@link ClassDoc} we want to check. + * @return a list of enum constants that will be documented. + */ + public List members(ClassDoc classDoc) { + return visibleMemberMap.getMembersFor(classDoc); + } + + /** + * Returns the visible member map for the enum constants of this class. + * + * @return the visible member map for the enum constants of this class. + */ + public VisibleMemberMap getVisibleMemberMap() { + return visibleMemberMap; + } + + /** + * summaryOrder.size() + */ + public boolean hasMembersToDocument() { + return enumConstants.size() > 0; + } + + /** + * Build the enum constant documentation. + * + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added + */ + public void buildEnumConstant(XMLNode node, Content memberDetailsTree) { + if (writer == null) { + return; } - - /** - * {@inheritDoc} - */ - public String getName() { - return "EnumConstantDetails"; - } - - /** - * Returns a list of enum constants that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @param classDoc the {@link ClassDoc} we want to check. - * @return a list of enum constants that will be documented. - */ - public List members(ClassDoc classDoc) { - return visibleMemberMap.getMembersFor(classDoc); - } - - /** - * Returns the visible member map for the enum constants of this class. - * - * @return the visible member map for the enum constants of this class. - */ - public VisibleMemberMap getVisibleMemberMap() { - return visibleMemberMap; - } - - /** - * summaryOrder.size() - */ - public boolean hasMembersToDocument() { - return enumConstants.size() > 0; - } - - /** - * Build the enum constant documentation. - * - * @param elements the XML elements that specify how to construct this - * documentation. - */ - public void buildEnumConstant(XMLNode node) { - if (writer == null) { - return; - } - for (currentEnumConstantsIndex = 0; - currentEnumConstantsIndex < enumConstants.size(); - currentEnumConstantsIndex++) { - buildChildren(node); - } - } - - /** - * Build the overall header. - */ - public void buildHeader(XMLNode node) { - writer.writeHeader( - classDoc, - configuration.getText("doclet.Enum_Constant_Detail")); - } - - /** - * Build the header for the individual enum constants. - */ - public void buildEnumConstantHeader(XMLNode node) { - writer.writeEnumConstantHeader( + int size = enumConstants.size(); + if (size > 0) { + Content enumConstantsDetailsTree = writer.getEnumConstantsDetailsTreeHeader( + classDoc, memberDetailsTree); + for (currentEnumConstantsIndex = 0; currentEnumConstantsIndex < size; + currentEnumConstantsIndex++) { + Content enumConstantsTree = writer.getEnumConstantsTreeHeader( (FieldDoc) enumConstants.get(currentEnumConstantsIndex), - currentEnumConstantsIndex == 0); + enumConstantsDetailsTree); + buildChildren(node, enumConstantsTree); + enumConstantsDetailsTree.addContent(writer.getEnumConstants( + enumConstantsTree, (currentEnumConstantsIndex == size - 1))); + } + memberDetailsTree.addContent( + writer.getEnumConstantsDetails(enumConstantsDetailsTree)); } + } - /** - * Build the signature. - */ - public void buildSignature(XMLNode node) { - writer.writeSignature( - (FieldDoc) enumConstants.get(currentEnumConstantsIndex)); - } + /** + * Build the signature. + * + * @param node the XML element that specifies which components to document + * @param enumConstantsTree the content tree to which the documentation will be added + */ + public void buildSignature(XMLNode node, Content enumConstantsTree) { + enumConstantsTree.addContent(writer.getSignature( + (FieldDoc) enumConstants.get(currentEnumConstantsIndex))); + } - /** - * Build the deprecation information. - */ - public void buildDeprecationInfo(XMLNode node) { - writer.writeDeprecated( - (FieldDoc) enumConstants.get(currentEnumConstantsIndex)); - } + /** + * Build the deprecation information. + * + * @param node the XML element that specifies which components to document + * @param enumConstantsTree the content tree to which the documentation will be added + */ + public void buildDeprecationInfo(XMLNode node, Content enumConstantsTree) { + writer.addDeprecated( + (FieldDoc) enumConstants.get(currentEnumConstantsIndex), + enumConstantsTree); + } - /** - * Build the comments for the enum constant. Do nothing if - * {@link Configuration#nocomment} is set to true. - */ - public void buildEnumConstantComments(XMLNode node) { - if (!configuration.nocomment) { - writer.writeComments( - (FieldDoc) enumConstants.get(currentEnumConstantsIndex)); - } + /** + * Build the comments for the enum constant. Do nothing if + * {@link Configuration#nocomment} is set to true. + * + * @param node the XML element that specifies which components to document + * @param enumConstantsTree the content tree to which the documentation will be added + */ + public void buildEnumConstantComments(XMLNode node, Content enumConstantsTree) { + if (!configuration.nocomment) { + writer.addComments( + (FieldDoc) enumConstants.get(currentEnumConstantsIndex), + enumConstantsTree); } + } - /** - * Build the tag information. - */ - public void buildTagInfo(XMLNode node) { - writer.writeTags( - (FieldDoc) enumConstants.get(currentEnumConstantsIndex)); - } + /** + * Build the tag information. + * + * @param node the XML element that specifies which components to document + * @param enumConstantsTree the content tree to which the documentation will be added + */ + public void buildTagInfo(XMLNode node, Content enumConstantsTree) { + writer.addTags( + (FieldDoc) enumConstants.get(currentEnumConstantsIndex), + enumConstantsTree); + } - /** - * Build the footer for the individual enum constants. - */ - public void buildEnumConstantFooter(XMLNode node) { - writer.writeEnumConstantFooter(); - } - - /** - * Build the overall footer. - */ - public void buildFooter(XMLNode node) { - writer.writeFooter(classDoc); - } - - /** - * Return the enum constant writer for this builder. - * - * @return the enum constant writer for this builder. - */ - public EnumConstantWriter getWriter() { - return writer; - } + /** + * Return the enum constant writer for this builder. + * + * @return the enum constant writer for this builder. + */ + public EnumConstantWriter getWriter() { + return writer; + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/FieldBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/FieldBuilder.java index 0e381f2ed0d..d5f5383e3f6 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/FieldBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/FieldBuilder.java @@ -25,10 +25,10 @@ package com.sun.tools.doclets.internal.toolkit.builders; +import java.util.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.javadoc.*; -import java.util.*; /** * Builds documentation for a field. @@ -38,197 +38,191 @@ import java.util.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public class FieldBuilder extends AbstractMemberBuilder { - /** - * The class whose fields are being documented. - */ - private ClassDoc classDoc; + /** + * The class whose fields are being documented. + */ + private ClassDoc classDoc; - /** - * The visible fields for the given class. - */ - private VisibleMemberMap visibleMemberMap; + /** + * The visible fields for the given class. + */ + private VisibleMemberMap visibleMemberMap; - /** - * The writer to output the field documentation. - */ - private FieldWriter writer; + /** + * The writer to output the field documentation. + */ + private FieldWriter writer; - /** - * The list of fields being documented. - */ - private List fields; + /** + * The list of fields being documented. + */ + private List fields; - /** - * The index of the current field that is being documented at this point - * in time. - */ - private int currentFieldIndex; + /** + * The index of the current field that is being documented at this point + * in time. + */ + private int currentFieldIndex; - /** - * Construct a new FieldBuilder. - * - * @param configuration the current configuration of the - * doclet. - */ - private FieldBuilder(Configuration configuration) { - super(configuration); + /** + * Construct a new FieldBuilder. + * + * @param configuration the current configuration of the + * doclet. + */ + private FieldBuilder(Configuration configuration) { + super(configuration); + } + + /** + * Construct a new FieldBuilder. + * + * @param configuration the current configuration of the doclet. + * @param classDoc the class whoses members are being documented. + * @param writer the doclet specific writer. + */ + public static FieldBuilder getInstance( + Configuration configuration, + ClassDoc classDoc, + FieldWriter writer) { + FieldBuilder builder = new FieldBuilder(configuration); + builder.classDoc = classDoc; + builder.writer = writer; + builder.visibleMemberMap = + new VisibleMemberMap( + classDoc, + VisibleMemberMap.FIELDS, + configuration.nodeprecated); + builder.fields = + new ArrayList(builder.visibleMemberMap.getLeafClassMembers( + configuration)); + if (configuration.getMemberComparator() != null) { + Collections.sort( + builder.fields, + configuration.getMemberComparator()); } + return builder; + } - /** - * Construct a new FieldBuilder. - * - * @param configuration the current configuration of the doclet. - * @param classDoc the class whoses members are being documented. - * @param writer the doclet specific writer. - */ - public static FieldBuilder getInstance( - Configuration configuration, - ClassDoc classDoc, - FieldWriter writer) { - FieldBuilder builder = new FieldBuilder(configuration); - builder.classDoc = classDoc; - builder.writer = writer; - builder.visibleMemberMap = - new VisibleMemberMap( - classDoc, - VisibleMemberMap.FIELDS, - configuration.nodeprecated); - builder.fields = - new ArrayList(builder.visibleMemberMap.getLeafClassMembers( - configuration)); - if (configuration.getMemberComparator() != null) { - Collections.sort( - builder.fields, - configuration.getMemberComparator()); - } - return builder; + /** + * {@inheritDoc} + */ + public String getName() { + return "FieldDetails"; + } + + /** + * Returns a list of fields that will be documented for the given class. + * This information can be used for doclet specific documentation + * generation. + * + * @param classDoc the {@link ClassDoc} we want to check. + * @return a list of fields that will be documented. + */ + public List members(ClassDoc classDoc) { + return visibleMemberMap.getMembersFor(classDoc); + } + + /** + * Returns the visible member map for the fields of this class. + * + * @return the visible member map for the fields of this class. + */ + public VisibleMemberMap getVisibleMemberMap() { + return visibleMemberMap; + } + + /** + * summaryOrder.size() + */ + public boolean hasMembersToDocument() { + return fields.size() > 0; + } + + /** + * Build the field documentation. + * + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added + */ + public void buildFieldDoc(XMLNode node, Content memberDetailsTree) { + if (writer == null) { + return; } - - /** - * {@inheritDoc} - */ - public String getName() { - return "FieldDetails"; - } - - /** - * Returns a list of fields that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @param classDoc the {@link ClassDoc} we want to check. - * @return a list of fields that will be documented. - */ - public List members(ClassDoc classDoc) { - return visibleMemberMap.getMembersFor(classDoc); - } - - /** - * Returns the visible member map for the fields of this class. - * - * @return the visible member map for the fields of this class. - */ - public VisibleMemberMap getVisibleMemberMap() { - return visibleMemberMap; - } - - /** - * summaryOrder.size() - */ - public boolean hasMembersToDocument() { - return fields.size() > 0; - } - - /** - * Build the field documentation. - * - * @param elements the XML elements that specify how to construct this - * documentation. - */ - public void buildFieldDoc(XMLNode node) { - if (writer == null) { - return; - } - for (currentFieldIndex = 0; - currentFieldIndex < fields.size(); - currentFieldIndex++) { - buildChildren(node); - } - } - - /** - * Build the overall header. - */ - public void buildHeader(XMLNode node) { - writer.writeHeader( - classDoc, - configuration.getText("doclet.Field_Detail")); - } - - /** - * Build the header for the individual field. - */ - public void buildFieldHeader(XMLNode node) { - writer.writeFieldHeader( + int size = fields.size(); + if (size > 0) { + Content fieldDetailsTree = writer.getFieldDetailsTreeHeader( + classDoc, memberDetailsTree); + for (currentFieldIndex = 0; currentFieldIndex < size; + currentFieldIndex++) { + Content fieldDocTree = writer.getFieldDocTreeHeader( (FieldDoc) fields.get(currentFieldIndex), - currentFieldIndex == 0); + fieldDetailsTree); + buildChildren(node, fieldDocTree); + fieldDetailsTree.addContent(writer.getFieldDoc( + fieldDocTree, (currentFieldIndex == size - 1))); + } + memberDetailsTree.addContent( + writer.getFieldDetails(fieldDetailsTree)); } + } - /** - * Build the signature. - */ - public void buildSignature(XMLNode node) { - writer.writeSignature((FieldDoc) fields.get(currentFieldIndex)); - } + /** + * Build the signature. + * + * @param node the XML element that specifies which components to document + * @param fieldDocTree the content tree to which the documentation will be added + */ + public void buildSignature(XMLNode node, Content fieldDocTree) { + fieldDocTree.addContent( + writer.getSignature((FieldDoc) fields.get(currentFieldIndex))); + } - /** - * Build the deprecation information. - */ - public void buildDeprecationInfo(XMLNode node) { - writer.writeDeprecated((FieldDoc) fields.get(currentFieldIndex)); - } + /** + * Build the deprecation information. + * + * @param node the XML element that specifies which components to document + * @param fieldDocTree the content tree to which the documentation will be added + */ + public void buildDeprecationInfo(XMLNode node, Content fieldDocTree) { + writer.addDeprecated( + (FieldDoc) fields.get(currentFieldIndex), fieldDocTree); + } - /** - * Build the comments for the field. Do nothing if - * {@link Configuration#nocomment} is set to true. - */ - public void buildFieldComments(XMLNode node) { - if (!configuration.nocomment) { - writer.writeComments((FieldDoc) fields.get(currentFieldIndex)); - } + /** + * Build the comments for the field. Do nothing if + * {@link Configuration#nocomment} is set to true. + * + * @param node the XML element that specifies which components to document + * @param fieldDocTree the content tree to which the documentation will be added + */ + public void buildFieldComments(XMLNode node, Content fieldDocTree) { + if (!configuration.nocomment) { + writer.addComments((FieldDoc) fields.get(currentFieldIndex), fieldDocTree); } + } - /** - * Build the tag information. - */ - public void buildTagInfo(XMLNode node) { - writer.writeTags((FieldDoc) fields.get(currentFieldIndex)); - } + /** + * Build the tag information. + * + * @param node the XML element that specifies which components to document + * @param fieldDocTree the content tree to which the documentation will be added + */ + public void buildTagInfo(XMLNode node, Content fieldDocTree) { + writer.addTags((FieldDoc) fields.get(currentFieldIndex), fieldDocTree); + } - /** - * Build the footer for the individual field. - */ - public void buildFieldFooter(XMLNode node) { - writer.writeFieldFooter(); - } - - /** - * Build the overall footer. - */ - public void buildFooter(XMLNode node) { - writer.writeFooter(classDoc); - } - - /** - * Return the field writer for this builder. - * - * @return the field writer for this builder. - */ - public FieldWriter getWriter() { - return writer; - } + /** + * Return the field writer for this builder. + * + * @return the field writer for this builder. + */ + public FieldWriter getWriter() { + return writer; + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/LayoutParser.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/LayoutParser.java index 3b413e7b75b..1d698a10349 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/LayoutParser.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/LayoutParser.java @@ -76,7 +76,7 @@ public class LayoutParser extends DefaultHandler { /** * Parse the XML specifying the layout of the documentation. * - * @return List the list of XML elements parsed. + * @return the list of XML elements parsed. */ public XMLNode parseXML(String root) { if (xmlElementsMap.containsKey(root)) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java index 404b2e6d1cf..7c65c523ee2 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java @@ -25,10 +25,10 @@ package com.sun.tools.doclets.internal.toolkit.builders; +import java.util.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.javadoc.*; -import java.util.*; /** * Builds the member summary. @@ -38,49 +38,50 @@ import java.util.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public class MemberSummaryBuilder extends AbstractMemberBuilder { - /** - * The XML root for this builder. - */ - public static final String NAME = "MemberSummary"; + /** + * The XML root for this builder. + */ + public static final String NAME = "MemberSummary"; - /** - * The visible members for the given class. - */ - private VisibleMemberMap[] visibleMemberMaps; + /** + * The visible members for the given class. + */ + private VisibleMemberMap[] visibleMemberMaps; - /** - * The member summary writers for the given class. - */ - private MemberSummaryWriter[] memberSummaryWriters; + /** + * The member summary writers for the given class. + */ + private MemberSummaryWriter[] memberSummaryWriters; - /** - * The type being documented. - */ - private ClassDoc classDoc; + /** + * The type being documented. + */ + private ClassDoc classDoc; - private MemberSummaryBuilder(Configuration configuration) { - super(configuration); - } + private MemberSummaryBuilder(Configuration configuration) { + super(configuration); + } - /** - * Construct a new MemberSummaryBuilder. - * - * @param classWriter the writer for the class whose members are being - * summarized. - * @param configuration the current configuration of the doclet. - */ - public static MemberSummaryBuilder getInstance( - ClassWriter classWriter, Configuration configuration) - throws Exception { - MemberSummaryBuilder builder = new MemberSummaryBuilder(configuration); - builder.classDoc = classWriter.getClassDoc(); - builder.init(classWriter); - return builder; - } + /** + * Construct a new MemberSummaryBuilder. + * + * @param classWriter the writer for the class whose members are being + * summarized. + * @param configuration the current configuration of the doclet. + */ + public static MemberSummaryBuilder getInstance( + ClassWriter classWriter, Configuration configuration) + throws Exception { + MemberSummaryBuilder builder = new MemberSummaryBuilder(configuration); + builder.classDoc = classWriter.getClassDoc(); + builder.init(classWriter); + return builder; + } /** * Construct a new MemberSummaryBuilder. @@ -90,8 +91,8 @@ public class MemberSummaryBuilder extends AbstractMemberBuilder { * @param configuration the current configuration of the doclet. */ public static MemberSummaryBuilder getInstance( - AnnotationTypeWriter annotationTypeWriter, Configuration configuration) - throws Exception { + AnnotationTypeWriter annotationTypeWriter, Configuration configuration) + throws Exception { MemberSummaryBuilder builder = new MemberSummaryBuilder(configuration); builder.classDoc = annotationTypeWriter.getAnnotationTypeDoc(); builder.init(annotationTypeWriter); @@ -100,200 +101,209 @@ public class MemberSummaryBuilder extends AbstractMemberBuilder { private void init(Object writer) throws Exception { visibleMemberMaps = - new VisibleMemberMap[VisibleMemberMap.NUM_MEMBER_TYPES]; + new VisibleMemberMap[VisibleMemberMap.NUM_MEMBER_TYPES]; for (int i = 0; i < VisibleMemberMap.NUM_MEMBER_TYPES; i++) { visibleMemberMaps[i] = - new VisibleMemberMap( + new VisibleMemberMap( classDoc, i, configuration.nodeprecated); } memberSummaryWriters = - new MemberSummaryWriter[VisibleMemberMap.NUM_MEMBER_TYPES]; + new MemberSummaryWriter[VisibleMemberMap.NUM_MEMBER_TYPES]; for (int i = 0; i < VisibleMemberMap.NUM_MEMBER_TYPES; i++) { if (classDoc.isAnnotationType()) { memberSummaryWriters[i] = visibleMemberMaps[i].noVisibleMembers()? null : configuration.getWriterFactory().getMemberSummaryWriter( - (AnnotationTypeWriter) writer, i); + (AnnotationTypeWriter) writer, i); } else { memberSummaryWriters[i] = visibleMemberMaps[i].noVisibleMembers()? null : configuration.getWriterFactory().getMemberSummaryWriter( - (ClassWriter) writer, i); + (ClassWriter) writer, i); } } } - /** - * {@inheritDoc} - */ - public String getName() { - return NAME; - } + /** + * {@inheritDoc} + */ + public String getName() { + return NAME; + } - /** - * Return the specified visible member map. - * - * @param type the type of visible member map to return. - * @return the specified visible member map. - * @throws ArrayIndexOutOfBoundsException when the type is invalid. - * @see VisibleMemberMap - */ - public VisibleMemberMap getVisibleMemberMap(int type) { - return visibleMemberMaps[type]; - } + /** + * Return the specified visible member map. + * + * @param type the type of visible member map to return. + * @return the specified visible member map. + * @throws ArrayIndexOutOfBoundsException when the type is invalid. + * @see VisibleMemberMap + */ + public VisibleMemberMap getVisibleMemberMap(int type) { + return visibleMemberMaps[type]; + } - /** - * Return the specified member summary writer. - * - * @param type the type of member summary writer to return. - * @return the specified member summary writer. - * @throws ArrayIndexOutOfBoundsException when the type is invalid. - * @see VisibleMemberMap - */ - public MemberSummaryWriter getMemberSummaryWriter(int type) { - return memberSummaryWriters[type]; - } + /** + * Return the specified member summary writer. + * + * @param type the type of member summary writer to return. + * @return the specified member summary writer. + * @throws ArrayIndexOutOfBoundsException when the type is invalid. + * @see VisibleMemberMap + */ + public MemberSummaryWriter getMemberSummaryWriter(int type) { + return memberSummaryWriters[type]; + } - /** - * Returns a list of methods that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @param classDoc the {@link ClassDoc} we want to check. - * @param type the type of members to return. - * @return a list of methods that will be documented. - * @see VisibleMemberMap - */ - public List members(int type) { - return visibleMemberMaps[type].getLeafClassMembers(configuration); - } + /** + * Returns a list of methods that will be documented for the given class. + * This information can be used for doclet specific documentation + * generation. + * + * @param classDoc the {@link ClassDoc} we want to check. + * @param type the type of members to return. + * @return a list of methods that will be documented. + * @see VisibleMemberMap + */ + public List members(int type) { + return visibleMemberMaps[type].getLeafClassMembers(configuration); + } - /** - * Return true it there are any members to summarize. - * - * @return true if there are any members to summarize. - */ - public boolean hasMembersToDocument() { + /** + * Return true it there are any members to summarize. + * + * @return true if there are any members to summarize. + */ + public boolean hasMembersToDocument() { if (classDoc instanceof AnnotationTypeDoc) { return ((AnnotationTypeDoc) classDoc).elements().length > 0; } - for (int i = 0; i < VisibleMemberMap.NUM_MEMBER_TYPES; i++) { - VisibleMemberMap members = visibleMemberMaps[i]; - if (!members.noVisibleMembers()) { - return true; - } - } - return false; - } - - /** - * Build the summary for the enum constants. - */ - public void buildEnumConstantsSummary(XMLNode node) { - buildSummary( - memberSummaryWriters[VisibleMemberMap.ENUM_CONSTANTS], - visibleMemberMaps[VisibleMemberMap.ENUM_CONSTANTS]); + for (int i = 0; i < VisibleMemberMap.NUM_MEMBER_TYPES; i++) { + VisibleMemberMap members = visibleMemberMaps[i]; + if (!members.noVisibleMembers()) { + return true; + } } + return false; + } /** - * Build the summary for the optional members. + * Build the summary for the enum constants. + * + * @param node the XML element that specifies which components to document + * @param memberSummaryTree the content tree to which the documentation will be added */ - public void buildAnnotationTypeOptionalMemberSummary(XMLNode node) { - buildSummary( - memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL], - visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL]); + public void buildEnumConstantsSummary(XMLNode node, Content memberSummaryTree) { + MemberSummaryWriter writer = + memberSummaryWriters[VisibleMemberMap.ENUM_CONSTANTS]; + VisibleMemberMap visibleMemberMap = + visibleMemberMaps[VisibleMemberMap.ENUM_CONSTANTS]; + addSummary(writer, visibleMemberMap, false, memberSummaryTree); } /** * Build the summary for the optional members. + * + * @param node the XML element that specifies which components to document + * @param memberSummaryTree the content tree to which the documentation will be added */ - public void buildAnnotationTypeRequiredMemberSummary(XMLNode node) { - buildSummary( - memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED], - visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED]); + public void buildAnnotationTypeOptionalMemberSummary(XMLNode node, Content memberSummaryTree) { + MemberSummaryWriter writer = + memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL]; + VisibleMemberMap visibleMemberMap = + visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL]; + addSummary(writer, visibleMemberMap, false, memberSummaryTree); } - /** - * Build the summary for the fields. - */ - public void buildFieldsSummary(XMLNode node) { - buildSummary( - memberSummaryWriters[VisibleMemberMap.FIELDS], - visibleMemberMaps[VisibleMemberMap.FIELDS]); - } + /** + * Build the summary for the optional members. + * + * @param node the XML element that specifies which components to document + * @param memberSummaryTree the content tree to which the documentation will be added + */ + public void buildAnnotationTypeRequiredMemberSummary(XMLNode node, Content memberSummaryTree) { + MemberSummaryWriter writer = + memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED]; + VisibleMemberMap visibleMemberMap = + visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED]; + addSummary(writer, visibleMemberMap, false, memberSummaryTree); + } - /** - * Build the inherited summary for the fields. - */ - public void buildFieldsInheritedSummary(XMLNode node) { - buildInheritedSummary( - memberSummaryWriters[VisibleMemberMap.FIELDS], - visibleMemberMaps[VisibleMemberMap.FIELDS]); - } + /** + * Build the summary for the fields. + * + * @param node the XML element that specifies which components to document + * @param memberSummaryTree the content tree to which the documentation will be added + */ + public void buildFieldsSummary(XMLNode node, Content memberSummaryTree) { + MemberSummaryWriter writer = + memberSummaryWriters[VisibleMemberMap.FIELDS]; + VisibleMemberMap visibleMemberMap = + visibleMemberMaps[VisibleMemberMap.FIELDS]; + addSummary(writer, visibleMemberMap, true, memberSummaryTree); + } - /** - * Build the summary for the nested classes. - */ - public void buildNestedClassesSummary(XMLNode node) { - buildSummary( - memberSummaryWriters[VisibleMemberMap.INNERCLASSES], - visibleMemberMaps[VisibleMemberMap.INNERCLASSES]); - } + /** + * Build the summary for the nested classes. + * + * @param node the XML element that specifies which components to document + * @param memberSummaryTree the content tree to which the documentation will be added + */ + public void buildNestedClassesSummary(XMLNode node, Content memberSummaryTree) { + MemberSummaryWriter writer = + memberSummaryWriters[VisibleMemberMap.INNERCLASSES]; + VisibleMemberMap visibleMemberMap = + visibleMemberMaps[VisibleMemberMap.INNERCLASSES]; + addSummary(writer, visibleMemberMap, true, memberSummaryTree); + } - /** - * Build the inherited summary for the nested classes. - */ - public void buildNestedClassesInheritedSummary(XMLNode node) { - buildInheritedSummary( - memberSummaryWriters[VisibleMemberMap.INNERCLASSES], - visibleMemberMaps[VisibleMemberMap.INNERCLASSES]); - } + /** + * Build the method summary. + * + * @param node the XML element that specifies which components to document + * @param memberSummaryTree the content tree to which the documentation will be added + */ + public void buildMethodsSummary(XMLNode node, Content memberSummaryTree) { + MemberSummaryWriter writer = + memberSummaryWriters[VisibleMemberMap.METHODS]; + VisibleMemberMap visibleMemberMap = + visibleMemberMaps[VisibleMemberMap.METHODS]; + addSummary(writer, visibleMemberMap, true, memberSummaryTree); + } - /** - * Build the method summary. - */ - public void buildMethodsSummary(XMLNode node) { - buildSummary( - memberSummaryWriters[VisibleMemberMap.METHODS], - visibleMemberMaps[VisibleMemberMap.METHODS]); - } + /** + * Build the constructor summary. + * + * @param node the XML element that specifies which components to document + * @param memberSummaryTree the content tree to which the documentation will be added + */ + public void buildConstructorsSummary(XMLNode node, Content memberSummaryTree) { + MemberSummaryWriter writer = + memberSummaryWriters[VisibleMemberMap.CONSTRUCTORS]; + VisibleMemberMap visibleMemberMap = + visibleMemberMaps[VisibleMemberMap.CONSTRUCTORS]; + addSummary(writer, visibleMemberMap, false, memberSummaryTree); + } - /** - * Build the inherited method summary. - */ - public void buildMethodsInheritedSummary(XMLNode node) { - buildInheritedSummary( - memberSummaryWriters[VisibleMemberMap.METHODS], - visibleMemberMaps[VisibleMemberMap.METHODS]); - } - - /** - * Build the constructor summary. - */ - public void buildConstructorsSummary(XMLNode node) { - buildSummary( - memberSummaryWriters[VisibleMemberMap.CONSTRUCTORS], - visibleMemberMaps[VisibleMemberMap.CONSTRUCTORS]); - } - - /** - * Build the member summary for the given members. - * - * @param writer the summary writer to write the output. - * @param visibleMemberMap the given members to summarize. - */ - private void buildSummary(MemberSummaryWriter writer, - VisibleMemberMap visibleMemberMap) { + /** + * Build the member summary for the given members. + * + * @param writer the summary writer to write the output. + * @param visibleMemberMap the given members to summarize. + * @param summaryTreeList list of content trees to which the documentation will be added + */ + private void buildSummary(MemberSummaryWriter writer, + VisibleMemberMap visibleMemberMap, LinkedList summaryTreeList) { List members = new ArrayList(visibleMemberMap.getLeafClassMembers( - configuration)); + configuration)); if (members.size() > 0) { Collections.sort(members); - writer.writeMemberSummaryHeader(classDoc); + Content tableTree = writer.getSummaryTableTree(classDoc); for (int i = 0; i < members.size(); i++) { ProgramElementDoc member = members.get(i); Tag[] firstSentenceTags = member.firstSentenceTags(); @@ -301,32 +311,32 @@ public class MemberSummaryBuilder extends AbstractMemberBuilder { //Inherit comments from overriden or implemented method if //necessary. DocFinder.Output inheritedDoc = - DocFinder.search(new DocFinder.Input((MethodDoc) member)); + DocFinder.search(new DocFinder.Input((MethodDoc) member)); if (inheritedDoc.holder != null && inheritedDoc.holder.firstSentenceTags().length > 0) { firstSentenceTags = inheritedDoc.holder.firstSentenceTags(); } } - writer.writeMemberSummary(classDoc, member, firstSentenceTags, - i == 0, i == members.size() - 1); + writer.addMemberSummary(classDoc, member, firstSentenceTags, tableTree, i); } - writer.writeMemberSummaryFooter(classDoc); - } + summaryTreeList.add(tableTree); } + } /** * Build the inherited member summary for the given methods. * - * @param writer the writer for this member summary. + * @param writer the writer for this member summary. * @param visibleMemberMap the map for the members to document. + * @param summaryTreeList list of content trees to which the documentation will be added */ - private void buildInheritedSummary(MemberSummaryWriter writer, - VisibleMemberMap visibleMemberMap) { + private void buildInheritedSummary(MemberSummaryWriter writer, + VisibleMemberMap visibleMemberMap, LinkedList summaryTreeList) { for (Iterator iter = visibleMemberMap.getVisibleClassesList().iterator(); iter.hasNext();) { ClassDoc inhclass = iter.next(); if (! (inhclass.isPublic() || - Util.isLinkable(inhclass, configuration))) { + Util.isLinkable(inhclass, configuration))) { continue; } if (inhclass == classDoc) { @@ -335,18 +345,45 @@ public class MemberSummaryBuilder extends AbstractMemberBuilder { List inhmembers = visibleMemberMap.getMembersFor(inhclass); if (inhmembers.size() > 0) { Collections.sort(inhmembers); - writer.writeInheritedMemberSummaryHeader(inhclass); + Content inheritedTree = writer.getInheritedSummaryHeader(inhclass); + Content linksTree = writer.getInheritedSummaryLinksTree(); for (int j = 0; j < inhmembers.size(); ++j) { - writer.writeInheritedMemberSummary( - inhclass.isPackagePrivate() && + writer.addInheritedMemberSummary( + inhclass.isPackagePrivate() && ! Util.isLinkable(inhclass, configuration) ? classDoc : inhclass, - inhmembers.get(j), - j == 0, - j == inhmembers.size() - 1); + inhmembers.get(j), + j == 0, + j == inhmembers.size() - 1, linksTree); } - writer.writeInheritedMemberSummaryFooter(inhclass); + inheritedTree.addContent(linksTree); + summaryTreeList.add(writer.getMemberTree(inheritedTree)); } } } + + /** + * Add the summary for the documentation. + * + * @param writer the writer for this member summary. + * @param visibleMemberMap the map for the members to document. + * @param showInheritedSummary true if inherited summary should be documented + * @param memberSummaryTree the content tree to which the documentation will be added + */ + private void addSummary(MemberSummaryWriter writer, + VisibleMemberMap visibleMemberMap, boolean showInheritedSummary, + Content memberSummaryTree) { + LinkedList summaryTreeList = new LinkedList(); + buildSummary(writer, visibleMemberMap, summaryTreeList); + if (showInheritedSummary) + buildInheritedSummary(writer, visibleMemberMap, summaryTreeList); + if (!summaryTreeList.isEmpty()) { + Content memberTree = writer.getMemberSummaryHeader( + classDoc, memberSummaryTree); + for (int i = 0; i < summaryTreeList.size(); i++) { + memberTree.addContent(summaryTreeList.get(i)); + } + memberSummaryTree.addContent(writer.getMemberTree(memberTree)); + } + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MethodBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MethodBuilder.java index 04816ac65f2..12c48f63424 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MethodBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MethodBuilder.java @@ -25,10 +25,10 @@ package com.sun.tools.doclets.internal.toolkit.builders; +import java.util.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.javadoc.*; -import java.util.*; /** * Builds documentation for a method. @@ -38,204 +38,199 @@ import java.util.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public class MethodBuilder extends AbstractMemberBuilder { - /** - * The index of the current field that is being documented at this point - * in time. - */ - private int currentMethodIndex; + /** + * The index of the current field that is being documented at this point + * in time. + */ + private int currentMethodIndex; - /** - * The class whose methods are being documented. - */ - private ClassDoc classDoc; + /** + * The class whose methods are being documented. + */ + private ClassDoc classDoc; - /** - * The visible methods for the given class. - */ - private VisibleMemberMap visibleMemberMap; + /** + * The visible methods for the given class. + */ + private VisibleMemberMap visibleMemberMap; - /** - * The writer to output the method documentation. - */ - private MethodWriter writer; + /** + * The writer to output the method documentation. + */ + private MethodWriter writer; - /** - * The methods being documented. - */ - private List methods; + /** + * The methods being documented. + */ + private List methods; - private MethodBuilder(Configuration configuration) { - super(configuration); - } + private MethodBuilder(Configuration configuration) { + super(configuration); + } - /** - * Construct a new MethodBuilder. - * - * @param configuration the current configuration of the doclet. - * @param classDoc the class whoses members are being documented. - * @param writer the doclet specific writer. - * - * @return an instance of a MethodBuilder. - */ - public static MethodBuilder getInstance( - Configuration configuration, - ClassDoc classDoc, - MethodWriter writer) { - MethodBuilder builder = new MethodBuilder(configuration); - builder.classDoc = classDoc; - builder.writer = writer; - builder.visibleMemberMap = - new VisibleMemberMap( - classDoc, - VisibleMemberMap.METHODS, - configuration.nodeprecated); - builder.methods = - new ArrayList(builder.visibleMemberMap.getLeafClassMembers( + /** + * Construct a new MethodBuilder. + * + * @param configuration the current configuration of the doclet. + * @param classDoc the class whoses members are being documented. + * @param writer the doclet specific writer. + * + * @return an instance of a MethodBuilder. + */ + public static MethodBuilder getInstance( + Configuration configuration, + ClassDoc classDoc, + MethodWriter writer) { + MethodBuilder builder = new MethodBuilder(configuration); + builder.classDoc = classDoc; + builder.writer = writer; + builder.visibleMemberMap = + new VisibleMemberMap( + classDoc, + VisibleMemberMap.METHODS, + configuration.nodeprecated); + builder.methods = + new ArrayList(builder.visibleMemberMap.getLeafClassMembers( configuration)); - if (configuration.getMemberComparator() != null) { - Collections.sort( - builder.methods, - configuration.getMemberComparator()); - } - return builder; + if (configuration.getMemberComparator() != null) { + Collections.sort( + builder.methods, + configuration.getMemberComparator()); } + return builder; + } - /** - * {@inheritDoc} - */ - public String getName() { - return "MethodDetails"; + /** + * {@inheritDoc} + */ + public String getName() { + return "MethodDetails"; + } + + /** + * Returns a list of methods that will be documented for the given class. + * This information can be used for doclet specific documentation + * generation. + * + * @param classDoc the {@link ClassDoc} we want to check. + * @return a list of methods that will be documented. + */ + public List members(ClassDoc classDoc) { + return visibleMemberMap.getMembersFor(classDoc); + } + + /** + * Returns the visible member map for the methods of this class. + * + * @return the visible member map for the methods of this class. + */ + public VisibleMemberMap getVisibleMemberMap() { + return visibleMemberMap; + } + + /** + * {@inheritDoc} + */ + public boolean hasMembersToDocument() { + return methods.size() > 0; + } + + /** + * Build the method documentation. + * + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added + */ + public void buildMethodDoc(XMLNode node, Content memberDetailsTree) { + if (writer == null) { + return; } - - /** - * Returns a list of methods that will be documented for the given class. - * This information can be used for doclet specific documentation - * generation. - * - * @param classDoc the {@link ClassDoc} we want to check. - * @return a list of methods that will be documented. - */ - public List members(ClassDoc classDoc) { - return visibleMemberMap.getMembersFor(classDoc); - } - - /** - * Returns the visible member map for the methods of this class. - * - * @return the visible member map for the methods of this class. - */ - public VisibleMemberMap getVisibleMemberMap() { - return visibleMemberMap; - } - - /** - * {@inheritDoc} - */ - public boolean hasMembersToDocument() { - return methods.size() > 0; - } - - /** - * Build the method documentation. - */ - public void buildMethodDoc(XMLNode node) { - if (writer == null) { - return; - } - for (currentMethodIndex = 0; - currentMethodIndex < methods.size(); - currentMethodIndex++) { - buildChildren(node); - } - } - - /** - * Build the overall header. - */ - public void buildHeader(XMLNode node) { - writer.writeHeader( - classDoc, - configuration.getText("doclet.Method_Detail")); - } - - /** - * Build the header for the individual method. - */ - public void buildMethodHeader(XMLNode node) { - writer.writeMethodHeader( + int size = methods.size(); + if (size > 0) { + Content methodDetailsTree = writer.getMethodDetailsTreeHeader( + classDoc, memberDetailsTree); + for (currentMethodIndex = 0; currentMethodIndex < size; + currentMethodIndex++) { + Content methodDocTree = writer.getMethodDocTreeHeader( (MethodDoc) methods.get(currentMethodIndex), - currentMethodIndex == 0); + methodDetailsTree); + buildChildren(node, methodDocTree); + methodDetailsTree.addContent(writer.getMethodDoc( + methodDocTree, (currentMethodIndex == size - 1))); + } + memberDetailsTree.addContent( + writer.getMethodDetails(methodDetailsTree)); } + } - /** - * Build the signature. - */ - public void buildSignature(XMLNode node) { - writer.writeSignature((MethodDoc) methods.get(currentMethodIndex)); - } + /** + * Build the signature. + * + * @param node the XML element that specifies which components to document + * @param methodDocTree the content tree to which the documentation will be added + */ + public void buildSignature(XMLNode node, Content methodDocTree) { + methodDocTree.addContent( + writer.getSignature((MethodDoc) methods.get(currentMethodIndex))); + } - /** - * Build the deprecation information. - */ - public void buildDeprecationInfo(XMLNode node) { - writer.writeDeprecated((MethodDoc) methods.get(currentMethodIndex)); - } + /** + * Build the deprecation information. + * + * @param node the XML element that specifies which components to document + * @param methodDocTree the content tree to which the documentation will be added + */ + public void buildDeprecationInfo(XMLNode node, Content methodDocTree) { + writer.addDeprecated( + (MethodDoc) methods.get(currentMethodIndex), methodDocTree); + } - /** - * Build the comments for the method. Do nothing if - * {@link Configuration#nocomment} is set to true. If this method - */ - public void buildMethodComments(XMLNode node) { - if (!configuration.nocomment) { + /** + * Build the comments for the method. Do nothing if + * {@link Configuration#nocomment} is set to true. + * + * @param node the XML element that specifies which components to document + * @param methodDocTree the content tree to which the documentation will be added + */ + public void buildMethodComments(XMLNode node, Content methodDocTree) { + if (!configuration.nocomment) { MethodDoc method = (MethodDoc) methods.get(currentMethodIndex); if (method.inlineTags().length == 0) { DocFinder.Output docs = DocFinder.search( - new DocFinder.Input(method)); + new DocFinder.Input(method)); method = docs.inlineTags != null && docs.inlineTags.length > 0 ? (MethodDoc) docs.holder : method; - } //NOTE: When we fix the bug where ClassDoc.interfaceTypes() does // not pass all implemented interfaces, holder will be the // interface type. For now, it is really the erasure. - writer.writeComments(method.containingClass(), method); - } + writer.addComments(method.containingClass(), method, methodDocTree); } + } + /** + * Build the tag information. + * + * @param node the XML element that specifies which components to document + * @param methodDocTree the content tree to which the documentation will be added + */ + public void buildTagInfo(XMLNode node, Content methodDocTree) { + writer.addTags((MethodDoc) methods.get(currentMethodIndex), + methodDocTree); + } - - /** - * Build the tag information. - */ - public void buildTagInfo(XMLNode node) { - writer.writeTags((MethodDoc) methods.get(currentMethodIndex)); - } - - /** - * Build the footer of the method. - */ - public void buildMethodFooter(XMLNode node) { - writer.writeMethodFooter(); - } - - /** - * Build the overall footer. - */ - public void buildFooter(XMLNode node) { - writer.writeFooter(classDoc); - } - - /** - * Return the method writer for this builder. - * - * @return the method writer for this builder. - */ - public MethodWriter getWriter() { - return writer; - } + /** + * Return the method writer for this builder. + * + * @return the method writer for this builder. + */ + public MethodWriter getWriter() { + return writer; + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java index acd382d35d4..b65920dfe97 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java @@ -25,10 +25,10 @@ package com.sun.tools.doclets.internal.toolkit.builders; +import java.io.*; +import com.sun.javadoc.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.*; -import com.sun.javadoc.*; -import java.io.*; /** * Builds the summary for a given package. @@ -42,281 +42,315 @@ import java.io.*; * @since 1.5 */ public class PackageSummaryBuilder extends AbstractBuilder { + /** + * The root element of the package summary XML is {@value}. + */ + public static final String ROOT = "PackageDoc"; - /** - * The root element of the package summary XML is {@value}. - */ - public static final String ROOT = "PackageDoc"; + /** + * The package being documented. + */ + private PackageDoc packageDoc; - /** - * The package being documented. - */ - private PackageDoc packageDoc; + /** + * The doclet specific writer that will output the result. + */ + private PackageSummaryWriter packageWriter; - /** - * The doclet specific writer that will output the result. - */ - private PackageSummaryWriter packageWriter; + /** + * The content that will be added to the package summary documentation tree. + */ + private Content contentTree; - private PackageSummaryBuilder(Configuration configuration) { - super(configuration); + private PackageSummaryBuilder(Configuration configuration) { + super(configuration); + } + + /** + * Construct a new PackageSummaryBuilder. + * @param configuration the current configuration of the doclet. + * @param pkg the package being documented. + * @param packageWriter the doclet specific writer that will output the + * result. + * + * @return an instance of a PackageSummaryBuilder. + */ + public static PackageSummaryBuilder getInstance( + Configuration configuration, + PackageDoc pkg, + PackageSummaryWriter packageWriter) { + PackageSummaryBuilder builder = + new PackageSummaryBuilder(configuration); + builder.packageDoc = pkg; + builder.packageWriter = packageWriter; + return builder; + } + + /** + * Build the package summary. + */ + public void build() throws IOException { + if (packageWriter == null) { + //Doclet does not support this output. + return; } + build(LayoutParser.getInstance(configuration).parseXML(ROOT), contentTree); + } - /** - * Construct a new PackageSummaryBuilder. - * @param configuration the current configuration of the doclet. - * @param pkg the package being documented. - * @param packageWriter the doclet specific writer that will output the - * result. - * - * @return an instance of a PackageSummaryBuilder. - */ - public static PackageSummaryBuilder getInstance( - Configuration configuration, - PackageDoc pkg, - PackageSummaryWriter packageWriter) { - PackageSummaryBuilder builder = - new PackageSummaryBuilder(configuration); - builder.packageDoc = pkg; - builder.packageWriter = packageWriter; - return builder; - } + /** + * {@inheritDoc} + */ + public String getName() { + return ROOT; + } - /** - * Build the package summary. - */ - public void build() throws IOException { - if (packageWriter == null) { - //Doclet does not support this output. - return; - } - build(LayoutParser.getInstance(configuration).parseXML(ROOT)); - } + /** + * Build the package documentation. + * + * @param node the XML element that specifies which components to document + * @param contentTree the content tree to which the documentation will be added + */ + public void buildPackageDoc(XMLNode node, Content contentTree) throws Exception { + contentTree = packageWriter.getPackageHeader( + Util.getPackageName(packageDoc)); + buildChildren(node, contentTree); + packageWriter.addPackageFooter(contentTree); + packageWriter.printDocument(contentTree); + packageWriter.close(); + Util.copyDocFiles( + configuration, + Util.getPackageSourcePath(configuration, packageDoc), + DirectoryManager.getDirectoryPath(packageDoc) + + File.separator + + DocletConstants.DOC_FILES_DIR_NAME, + true); + } - /** - * {@inheritDoc} - */ - public String getName() { - return ROOT; - } + /** + * Build the content for the package doc. + * + * @param node the XML element that specifies which components to document + * @param contentTree the content tree to which the package contents + * will be added + */ + public void buildContent(XMLNode node, Content contentTree) { + Content packageContentTree = packageWriter.getContentHeader(); + buildChildren(node, packageContentTree); + contentTree.addContent(packageContentTree); + } - /** - * Build the package documentation. - */ - public void buildPackageDoc(XMLNode node) throws Exception { - buildChildren(node); - packageWriter.close(); - Util.copyDocFiles( - configuration, - Util.getPackageSourcePath(configuration, packageDoc), - DirectoryManager.getDirectoryPath(packageDoc) - + File.separator - + DocletConstants.DOC_FILES_DIR_NAME, - true); - } + /** + * Build the package summary. + * + * @param node the XML element that specifies which components to document + * @param packageContentTree the package content tree to which the summaries will + * be added + */ + public void buildSummary(XMLNode node, Content packageContentTree) { + Content summaryContentTree = packageWriter.getSummaryHeader(); + buildChildren(node, summaryContentTree); + packageContentTree.addContent(summaryContentTree); + } - /** - * Build the header of the summary. - */ - public void buildPackageHeader(XMLNode node) { - packageWriter.writePackageHeader(Util.getPackageName(packageDoc)); - } - - /** - * Build the description of the summary. - */ - public void buildPackageDescription(XMLNode node) { - if (configuration.nocomment) { - return; - } - packageWriter.writePackageDescription(); - } - - /** - * Build the tags of the summary. - */ - public void buildPackageTags(XMLNode node) { - if (configuration.nocomment) { - return; - } - packageWriter.writePackageTags(); - } - - /** - * Build the package summary. - */ - public void buildSummary(XMLNode node) { - buildChildren(node); - } - - /** - * Build the overall header. - */ - public void buildSummaryHeader(XMLNode node) { - packageWriter.writeSummaryHeader(); - } - - /** - * Build the overall footer. - */ - public void buildSummaryFooter(XMLNode node) { - packageWriter.writeSummaryFooter(); - } - - /** - * Build the summary for the classes in this package. - */ - public void buildClassSummary(XMLNode node) { - String classTableSummary = - configuration.getText("doclet.Member_Table_Summary", - configuration.getText("doclet.Class_Summary"), - configuration.getText("doclet.classes")); - String[] classTableHeader = new String[] { - configuration.getText("doclet.Class"), - configuration.getText("doclet.Description") - }; - ClassDoc[] classes = - packageDoc.isIncluded() - ? packageDoc.ordinaryClasses() - : configuration.classDocCatalog.ordinaryClasses( - Util.getPackageName(packageDoc)); - if (classes.length > 0) { - packageWriter.writeClassesSummary( - classes, - configuration.getText("doclet.Class_Summary"), - classTableSummary, classTableHeader); - } - } - - /** - * Build the summary for the interfaces in this package. - */ - public void buildInterfaceSummary(XMLNode node) { - String interfaceTableSummary = - configuration.getText("doclet.Member_Table_Summary", + /** + * Build the summary for the interfaces in this package. + * + * @param node the XML element that specifies which components to document + * @param summaryContentTree the summary tree to which the interface summary + * will be added + */ + public void buildInterfaceSummary(XMLNode node, Content summaryContentTree) { + String interfaceTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Interface_Summary"), + configuration.getText("doclet.interfaces")); + String[] interfaceTableHeader = new String[] { + configuration.getText("doclet.Interface"), + configuration.getText("doclet.Description") + }; + ClassDoc[] interfaces = + packageDoc.isIncluded() + ? packageDoc.interfaces() + : configuration.classDocCatalog.interfaces( + Util.getPackageName(packageDoc)); + if (interfaces.length > 0) { + packageWriter.addClassesSummary( + interfaces, configuration.getText("doclet.Interface_Summary"), - configuration.getText("doclet.interfaces")); - String[] interfaceTableHeader = new String[] { - configuration.getText("doclet.Interface"), - configuration.getText("doclet.Description") - }; - ClassDoc[] interfaces = - packageDoc.isIncluded() - ? packageDoc.interfaces() - : configuration.classDocCatalog.interfaces( - Util.getPackageName(packageDoc)); - if (interfaces.length > 0) { - packageWriter.writeClassesSummary( - interfaces, - configuration.getText("doclet.Interface_Summary"), - interfaceTableSummary, interfaceTableHeader); - } + interfaceTableSummary, interfaceTableHeader, summaryContentTree); } + } - /** - * Build the summary for the enums in this package. - */ - public void buildAnnotationTypeSummary(XMLNode node) { - String annotationtypeTableSummary = - configuration.getText("doclet.Member_Table_Summary", - configuration.getText("doclet.Annotation_Types_Summary"), - configuration.getText("doclet.annotationtypes")); - String[] annotationtypeTableHeader = new String[] { - configuration.getText("doclet.AnnotationType"), - configuration.getText("doclet.Description") - }; - ClassDoc[] annotationTypes = - packageDoc.isIncluded() - ? packageDoc.annotationTypes() - : configuration.classDocCatalog.annotationTypes( - Util.getPackageName(packageDoc)); - if (annotationTypes.length > 0) { - packageWriter.writeClassesSummary( - annotationTypes, - configuration.getText("doclet.Annotation_Types_Summary"), - annotationtypeTableSummary, annotationtypeTableHeader); - } + /** + * Build the summary for the classes in this package. + * + * @param node the XML element that specifies which components to document + * @param summaryContentTree the summary tree to which the class summary will + * be added + */ + public void buildClassSummary(XMLNode node, Content summaryContentTree) { + String classTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Class_Summary"), + configuration.getText("doclet.classes")); + String[] classTableHeader = new String[] { + configuration.getText("doclet.Class"), + configuration.getText("doclet.Description") + }; + ClassDoc[] classes = + packageDoc.isIncluded() + ? packageDoc.ordinaryClasses() + : configuration.classDocCatalog.ordinaryClasses( + Util.getPackageName(packageDoc)); + if (classes.length > 0) { + packageWriter.addClassesSummary( + classes, + configuration.getText("doclet.Class_Summary"), + classTableSummary, classTableHeader, summaryContentTree); } + } - /** - * Build the summary for the enums in this package. - */ - public void buildEnumSummary(XMLNode node) { - String enumTableSummary = - configuration.getText("doclet.Member_Table_Summary", + /** + * Build the summary for the enums in this package. + * + * @param node the XML element that specifies which components to document + * @param summaryContentTree the summary tree to which the enum summary will + * be added + */ + public void buildEnumSummary(XMLNode node, Content summaryContentTree) { + String enumTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Enum_Summary"), + configuration.getText("doclet.enums")); + String[] enumTableHeader = new String[] { + configuration.getText("doclet.Enum"), + configuration.getText("doclet.Description") + }; + ClassDoc[] enums = + packageDoc.isIncluded() + ? packageDoc.enums() + : configuration.classDocCatalog.enums( + Util.getPackageName(packageDoc)); + if (enums.length > 0) { + packageWriter.addClassesSummary( + enums, configuration.getText("doclet.Enum_Summary"), - configuration.getText("doclet.enums")); - String[] enumTableHeader = new String[] { - configuration.getText("doclet.Enum"), - configuration.getText("doclet.Description") - }; - ClassDoc[] enums = - packageDoc.isIncluded() - ? packageDoc.enums() - : configuration.classDocCatalog.enums( - Util.getPackageName(packageDoc)); - if (enums.length > 0) { - packageWriter.writeClassesSummary( - enums, - configuration.getText("doclet.Enum_Summary"), - enumTableSummary, enumTableHeader); - } + enumTableSummary, enumTableHeader, summaryContentTree); } + } - /** - * Build the summary for the exceptions in this package. - */ - public void buildExceptionSummary(XMLNode node) { - String exceptionTableSummary = - configuration.getText("doclet.Member_Table_Summary", + /** + * Build the summary for the exceptions in this package. + * + * @param node the XML element that specifies which components to document + * @param summaryContentTree the summary tree to which the exception summary will + * be added + */ + public void buildExceptionSummary(XMLNode node, Content summaryContentTree) { + String exceptionTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Exception_Summary"), + configuration.getText("doclet.exceptions")); + String[] exceptionTableHeader = new String[] { + configuration.getText("doclet.Exception"), + configuration.getText("doclet.Description") + }; + ClassDoc[] exceptions = + packageDoc.isIncluded() + ? packageDoc.exceptions() + : configuration.classDocCatalog.exceptions( + Util.getPackageName(packageDoc)); + if (exceptions.length > 0) { + packageWriter.addClassesSummary( + exceptions, configuration.getText("doclet.Exception_Summary"), - configuration.getText("doclet.exceptions")); - String[] exceptionTableHeader = new String[] { - configuration.getText("doclet.Exception"), - configuration.getText("doclet.Description") - }; - ClassDoc[] exceptions = - packageDoc.isIncluded() - ? packageDoc.exceptions() - : configuration.classDocCatalog.exceptions( - Util.getPackageName(packageDoc)); - if (exceptions.length > 0) { - packageWriter.writeClassesSummary( - exceptions, - configuration.getText("doclet.Exception_Summary"), - exceptionTableSummary, exceptionTableHeader); - } + exceptionTableSummary, exceptionTableHeader, summaryContentTree); } + } - /** - * Build the summary for the errors in this package. - */ - public void buildErrorSummary(XMLNode node) { - String errorTableSummary = - configuration.getText("doclet.Member_Table_Summary", + /** + * Build the summary for the errors in this package. + * + * @param node the XML element that specifies which components to document + * @param summaryContentTree the summary tree to which the error summary will + * be added + */ + public void buildErrorSummary(XMLNode node, Content summaryContentTree) { + String errorTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Error_Summary"), + configuration.getText("doclet.errors")); + String[] errorTableHeader = new String[] { + configuration.getText("doclet.Error"), + configuration.getText("doclet.Description") + }; + ClassDoc[] errors = + packageDoc.isIncluded() + ? packageDoc.errors() + : configuration.classDocCatalog.errors( + Util.getPackageName(packageDoc)); + if (errors.length > 0) { + packageWriter.addClassesSummary( + errors, configuration.getText("doclet.Error_Summary"), - configuration.getText("doclet.errors")); - String[] errorTableHeader = new String[] { - configuration.getText("doclet.Error"), - configuration.getText("doclet.Description") - }; - ClassDoc[] errors = - packageDoc.isIncluded() - ? packageDoc.errors() - : configuration.classDocCatalog.errors( - Util.getPackageName(packageDoc)); - if (errors.length > 0) { - packageWriter.writeClassesSummary( - errors, - configuration.getText("doclet.Error_Summary"), - errorTableSummary, errorTableHeader); - } + errorTableSummary, errorTableHeader, summaryContentTree); } + } - /** - * Build the footer of the summary. - */ - public void buildPackageFooter(XMLNode node) { - packageWriter.writePackageFooter(); + /** + * Build the summary for the annotation type in this package. + * + * @param node the XML element that specifies which components to document + * @param summaryContentTree the summary tree to which the annotation type + * summary will be added + */ + public void buildAnnotationTypeSummary(XMLNode node, Content summaryContentTree) { + String annotationtypeTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Annotation_Types_Summary"), + configuration.getText("doclet.annotationtypes")); + String[] annotationtypeTableHeader = new String[] { + configuration.getText("doclet.AnnotationType"), + configuration.getText("doclet.Description") + }; + ClassDoc[] annotationTypes = + packageDoc.isIncluded() + ? packageDoc.annotationTypes() + : configuration.classDocCatalog.annotationTypes( + Util.getPackageName(packageDoc)); + if (annotationTypes.length > 0) { + packageWriter.addClassesSummary( + annotationTypes, + configuration.getText("doclet.Annotation_Types_Summary"), + annotationtypeTableSummary, annotationtypeTableHeader, + summaryContentTree); } + } + + /** + * Build the description of the summary. + * + * @param node the XML element that specifies which components to document + * @param packageContentTree the tree to which the package description will + * be added + */ + public void buildPackageDescription(XMLNode node, Content packageContentTree) { + if (configuration.nocomment) { + return; + } + packageWriter.addPackageDescription(packageContentTree); + } + + /** + * Build the tags of the summary. + * + * @param node the XML element that specifies which components to document + * @param packageContentTree the tree to which the package tags will be added + */ + public void buildPackageTags(XMLNode node, Content packageContentTree) { + if (configuration.nocomment) { + return; + } + packageWriter.addPackageTags(packageContentTree); + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java index 5cfc42a9009..2ec990a5c0e 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java @@ -27,7 +27,6 @@ package com.sun.tools.doclets.internal.toolkit.builders; import java.io.*; import java.util.*; - import com.sun.javadoc.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.internal.toolkit.*; @@ -87,6 +86,11 @@ public class SerializedFormBuilder extends AbstractBuilder { */ protected MemberDoc currentMember; + /** + * The content that will be added to the serialized form documentation tree. + */ + private Content contentTree; + private SerializedFormBuilder(Configuration configuration) { super(configuration); } @@ -117,7 +121,7 @@ public class SerializedFormBuilder extends AbstractBuilder { } catch (Exception e) { throw new DocletAbortException(); } - build(LayoutParser.getInstance(configuration).parseXML(NAME)); + build(LayoutParser.getInstance(configuration).parseXML(NAME), contentTree); writer.close(); } @@ -130,34 +134,44 @@ public class SerializedFormBuilder extends AbstractBuilder { /** * Build the serialized form. + * + * @param node the XML element that specifies which components to document + * @param serializedTree content tree to which the documentation will be added */ - public void buildSerializedForm(XMLNode node) throws Exception { - buildChildren(node); + public void buildSerializedForm(XMLNode node, Content serializedTree) throws Exception { + serializedTree = writer.getHeader(configuration.getText( + "doclet.Serialized_Form")); + buildChildren(node, serializedTree); + writer.addFooter(serializedTree); + writer.printDocument(serializedTree); writer.close(); } /** - * Build the header. + * Build the serialized form summaries. + * + * @param node the XML element that specifies which components to document + * @param serializedTree content tree to which the documentation will be added */ - public void buildHeader(XMLNode node) { - writer.writeHeader(configuration.getText("doclet.Serialized_Form")); - } - - /** - * Build the contents. - */ - public void buildSerializedFormSummaries(XMLNode node) { + public void buildSerializedFormSummaries(XMLNode node, Content serializedTree) { + Content serializedSummariesTree = writer.getSerializedSummariesHeader(); PackageDoc[] packages = configuration.packages; for (int i = 0; i < packages.length; i++) { currentPackage = packages[i]; - buildChildren(node); + buildChildren(node, serializedSummariesTree); } + serializedTree.addContent(writer.getSerializedContent( + serializedSummariesTree)); } /** - * Build the package serialized for for the current package being processed. + * Build the package serialized form for the current package being processed. + * + * @param node the XML element that specifies which components to document + * @param serializedSummariesTree content tree to which the documentation will be added */ - public void buildPackageSerializedForm(XMLNode node) { + public void buildPackageSerializedForm(XMLNode node, Content serializedSummariesTree) { + Content packageSerializedTree = writer.getPackageSerializedHeader(); String foo = currentPackage.name(); ClassDoc[] classes = currentPackage.allClasses(false); if (classes == null || classes.length == 0) { @@ -169,14 +183,29 @@ public class SerializedFormBuilder extends AbstractBuilder { if (!serialClassFoundToDocument(classes)) { return; } - buildChildren(node); + buildChildren(node, packageSerializedTree); + serializedSummariesTree.addContent(packageSerializedTree); } - public void buildPackageHeader(XMLNode node) { - writer.writePackageHeader(Util.getPackageName(currentPackage)); + /** + * Build the package header. + * + * @param node the XML element that specifies which components to document + * @param packageSerializedTree content tree to which the documentation will be added + */ + public void buildPackageHeader(XMLNode node, Content packageSerializedTree) { + packageSerializedTree.addContent(writer.getPackageHeader( + Util.getPackageName(currentPackage))); } - public void buildClassSerializedForm(XMLNode node) { + /** + * Build the class serialized form. + * + * @param node the XML element that specifies which components to document + * @param packageSerializedTree content tree to which the documentation will be added + */ + public void buildClassSerializedForm(XMLNode node, Content packageSerializedTree) { + Content classSerializedTree = writer.getClassSerializedHeader(); ClassDoc[] classes = currentPackage.allClasses(false); Arrays.sort(classes); for (int j = 0; j < classes.length; j++) { @@ -187,35 +216,293 @@ public class SerializedFormBuilder extends AbstractBuilder { if(!serialClassInclude(currentClass)) { continue; } - buildChildren(node); + Content classTree = writer.getClassHeader(currentClass); + buildChildren(node, classTree); + classSerializedTree.addContent(classTree); } } - } - - public void buildClassHeader(XMLNode node) { - writer.writeClassHeader(currentClass); + packageSerializedTree.addContent(classSerializedTree); } /** * Build the serial UID information for the given class. + * + * @param node the XML element that specifies which components to document + * @param classTree content tree to which the serial UID information will be added */ - public void buildSerialUIDInfo(XMLNode node) { + public void buildSerialUIDInfo(XMLNode node, Content classTree) { + Content serialUidTree = writer.getSerialUIDInfoHeader(); FieldDoc[] fields = currentClass.fields(false); for (int i = 0; i < fields.length; i++) { if (fields[i].name().equals("serialVersionUID") && fields[i].constantValueExpression() != null) { - writer.writeSerialUIDInfo(SERIAL_VERSION_UID_HEADER, - fields[i].constantValueExpression()); - return; + writer.addSerialUIDInfo(SERIAL_VERSION_UID_HEADER, + fields[i].constantValueExpression(), serialUidTree); + break; + } + } + classTree.addContent(serialUidTree); + } + + /** + * Build the summaries for the methods and fields. + * + * @param node the XML element that specifies which components to document + * @param classTree content tree to which the documentation will be added + */ + public void buildClassContent(XMLNode node, Content classTree) { + Content classContentTree = writer.getClassContentHeader(); + buildChildren(node, classContentTree); + classTree.addContent(classContentTree); + } + + /** + * Build the summaries for the methods that belong to the given + * class. + * + * @param node the XML element that specifies which components to document + * @param classContentTree content tree to which the documentation will be added + */ + public void buildSerializableMethods(XMLNode node, Content classContentTree) { + Content serializableMethodTree = methodWriter.getSerializableMethodsHeader(); + MemberDoc[] members = currentClass.serializationMethods(); + int membersLength = members.length; + if (membersLength > 0) { + for (int i = 0; i < membersLength; i++) { + currentMember = members[i]; + Content methodsContentTree = methodWriter.getMethodsContentHeader( + (i == membersLength - 1)); + buildChildren(node, methodsContentTree); + serializableMethodTree.addContent(methodsContentTree); + } + } + if (currentClass.serializationMethods().length > 0) { + classContentTree.addContent(methodWriter.getSerializableMethods( + configuration.getText("doclet.Serialized_Form_methods"), + serializableMethodTree)); + if (currentClass.isSerializable() && !currentClass.isExternalizable()) { + if (currentClass.serializationMethods().length == 0) { + Content noCustomizationMsg = methodWriter.getNoCustomizationMsg( + configuration.getText( + "doclet.Serializable_no_customization")); + classContentTree.addContent(methodWriter.getSerializableMethods( + configuration.getText("doclet.Serialized_Form_methods"), + noCustomizationMsg)); + } } } } /** - * Build the footer. + * Build the method sub header. + * + * @param node the XML element that specifies which components to document + * @param methodsContentTree content tree to which the documentation will be added */ - public void buildFooter(XMLNode node) { - writer.writeFooter(); + public void buildMethodSubHeader(XMLNode node, Content methodsContentTree) { + methodWriter.addMemberHeader((MethodDoc)currentMember, methodsContentTree); + } + + /** + * Build the deprecated method description. + * + * @param node the XML element that specifies which components to document + * @param methodsContentTree content tree to which the documentation will be added + */ + public void buildDeprecatedMethodInfo(XMLNode node, Content methodsContentTree) { + methodWriter.addDeprecatedMemberInfo((MethodDoc) currentMember, methodsContentTree); + } + + /** + * Build the information for the method. + * + * @param node the XML element that specifies which components to document + * @param methodsContentTree content tree to which the documentation will be added + */ + public void buildMethodInfo(XMLNode node, Content methodsContentTree) { + if(configuration.nocomment){ + return; + } + buildChildren(node, methodsContentTree); + } + + /** + * Build method description. + * + * @param node the XML element that specifies which components to document + * @param methodsContentTree content tree to which the documentation will be added + */ + public void buildMethodDescription(XMLNode node, Content methodsContentTree) { + methodWriter.addMemberDescription((MethodDoc) currentMember, methodsContentTree); + } + + /** + * Build the method tags. + * + * @param node the XML element that specifies which components to document + * @param methodsContentTree content tree to which the documentation will be added + */ + public void buildMethodTags(XMLNode node, Content methodsContentTree) { + methodWriter.addMemberTags((MethodDoc) currentMember, methodsContentTree); + MethodDoc method = (MethodDoc)currentMember; + if (method.name().compareTo("writeExternal") == 0 + && method.tags("serialData").length == 0) { + if (configuration.serialwarn) { + configuration.getDocletSpecificMsg().warning( + currentMember.position(), "doclet.MissingSerialDataTag", + method.containingClass().qualifiedName(), method.name()); + } + } + } + + /** + * Build the field header. + * + * @param node the XML element that specifies which components to document + * @param classContentTree content tree to which the documentation will be added + */ + public void buildFieldHeader(XMLNode node, Content classContentTree) { + if (currentClass.serializableFields().length > 0) { + buildFieldSerializationOverview(currentClass, classContentTree); + } + } + + /** + * Build the serialization overview for the given class. + * + * @param classDoc the class to print the overview for. + * @param classContentTree content tree to which the documentation will be added + */ + public void buildFieldSerializationOverview(ClassDoc classDoc, Content classContentTree) { + if (classDoc.definesSerializableFields()) { + FieldDoc serialPersistentField = + Util.asList(classDoc.serializableFields()).get(0); + // Check to see if there are inline comments, tags or deprecation + // information to be printed. + if (fieldWriter.shouldPrintOverview(serialPersistentField)) { + Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader(); + Content fieldsOverviewContentTree = fieldWriter.getFieldsContentHeader(true); + fieldWriter.addMemberDeprecatedInfo(serialPersistentField, + fieldsOverviewContentTree); + if (!configuration.nocomment) { + fieldWriter.addMemberDescription(serialPersistentField, + fieldsOverviewContentTree); + fieldWriter.addMemberTags(serialPersistentField, + fieldsOverviewContentTree); + } + serializableFieldsTree.addContent(fieldsOverviewContentTree); + classContentTree.addContent(fieldWriter.getSerializableFields( + configuration.getText("doclet.Serialized_Form_class"), + serializableFieldsTree)); + } + } + } + + /** + * Build the summaries for the fields that belong to the given class. + * + * @param node the XML element that specifies which components to document + * @param classContentTree content tree to which the documentation will be added + */ + public void buildSerializableFields(XMLNode node, Content classContentTree) { + MemberDoc[] members = currentClass.serializableFields(); + int membersLength = members.length; + if (membersLength > 0) { + Content serializableFieldsTree = fieldWriter.getSerializableFieldsHeader(); + for (int i = 0; i < membersLength; i++) { + currentMember = members[i]; + if (!currentClass.definesSerializableFields()) { + Content fieldsContentTree = fieldWriter.getFieldsContentHeader( + (i == membersLength - 1)); + buildChildren(node, fieldsContentTree); + serializableFieldsTree.addContent(fieldsContentTree); + } + else { + buildSerialFieldTagsInfo(serializableFieldsTree); + } + } + classContentTree.addContent(fieldWriter.getSerializableFields( + configuration.getText("doclet.Serialized_Form_fields"), + serializableFieldsTree)); + } + } + + /** + * Build the field sub header. + * + * @param node the XML element that specifies which components to document + * @param fieldsContentTree content tree to which the documentation will be added + */ + public void buildFieldSubHeader(XMLNode node, Content fieldsContentTree) { + if (!currentClass.definesSerializableFields()) { + FieldDoc field = (FieldDoc) currentMember; + fieldWriter.addMemberHeader(field.type().asClassDoc(), + field.type().typeName(), field.type().dimension(), field.name(), + fieldsContentTree); + } + } + + /** + * Build the field deprecation information. + * + * @param node the XML element that specifies which components to document + * @param fieldsContentTree content tree to which the documentation will be added + */ + public void buildFieldDeprecationInfo(XMLNode node, Content fieldsContentTree) { + if (!currentClass.definesSerializableFields()) { + FieldDoc field = (FieldDoc)currentMember; + fieldWriter.addMemberDeprecatedInfo(field, fieldsContentTree); + } + } + + /** + * Build the serial field tags information. + * + * @param serializableFieldsTree content tree to which the documentation will be added + */ + public void buildSerialFieldTagsInfo(Content serializableFieldsTree) { + if(configuration.nocomment){ + return; + } + FieldDoc field = (FieldDoc)currentMember; + // Process Serializable Fields specified as array of + // ObjectStreamFields. Print a member for each serialField tag. + // (There should be one serialField tag per ObjectStreamField + // element.) + SerialFieldTag[] tags = field.serialFieldTags(); + Arrays.sort(tags); + int tagsLength = tags.length; + for (int i = 0; i < tagsLength; i++) { + Content fieldsContentTree = fieldWriter.getFieldsContentHeader( + (i == tagsLength - 1)); + fieldWriter.addMemberHeader(tags[i].fieldTypeDoc(), + tags[i].fieldType(), "", tags[i].fieldName(), fieldsContentTree); + fieldWriter.addMemberDescription(tags[i], fieldsContentTree); + serializableFieldsTree.addContent(fieldsContentTree); + } + } + + /** + * Build the field information. + * + * @param node the XML element that specifies which components to document + * @param fieldsContentTree content tree to which the documentation will be added + */ + public void buildFieldInfo(XMLNode node, Content fieldsContentTree) { + if(configuration.nocomment){ + return; + } + FieldDoc field = (FieldDoc)currentMember; + ClassDoc cd = field.containingClass(); + // Process default Serializable field. + if ((field.tags("serial").length == 0) && ! field.isSynthetic() + && configuration.serialwarn) { + configuration.message.warning(field.position(), + "doclet.MissingSerialTag", cd.qualifiedName(), + field.name()); + } + fieldWriter.addMemberDescription(field, fieldsContentTree); + fieldWriter.addMemberTags(field, fieldsContentTree); } /** @@ -297,208 +584,4 @@ public class SerializedFormBuilder extends AbstractBuilder { } return false; } - - /** - * Build the method header. - */ - public void buildMethodHeader(XMLNode node) { - if (currentClass.serializationMethods().length > 0) { - methodWriter.writeHeader( - configuration.getText("doclet.Serialized_Form_methods")); - if (currentClass.isSerializable() && !currentClass.isExternalizable()) { - if (currentClass.serializationMethods().length == 0) { - methodWriter.writeNoCustomizationMsg( - configuration.getText( - "doclet.Serializable_no_customization")); - } - } - } - } - - /** - * Build the method sub header. - */ - public void buildMethodSubHeader(XMLNode node) { - methodWriter.writeMemberHeader((MethodDoc) currentMember); - } - - /** - * Build the deprecated method description. - */ - public void buildDeprecatedMethodInfo(XMLNode node) { - methodWriter.writeDeprecatedMemberInfo((MethodDoc) currentMember); - } - - /** - * Build method tags. - */ - public void buildMethodDescription(XMLNode node) { - methodWriter.writeMemberDescription((MethodDoc) currentMember); - } - - /** - * Build the method tags. - */ - public void buildMethodTags(XMLNode node) { - methodWriter.writeMemberTags((MethodDoc) currentMember); - MethodDoc method = (MethodDoc)currentMember; - if (method.name().compareTo("writeExternal") == 0 - && method.tags("serialData").length == 0) { - if (configuration.serialwarn) { - configuration.getDocletSpecificMsg().warning( - currentMember.position(), "doclet.MissingSerialDataTag", - method.containingClass().qualifiedName(), method.name()); - } - } - } - - /** - * build the information for the method. - */ - public void buildMethodInfo(XMLNode node) { - if(configuration.nocomment){ - return; - } - buildChildren(node); - } - - /** - * Build the method footer. - */ - public void buildMethodFooter(XMLNode node) { - methodWriter.writeMemberFooter(); - } - - /** - * Build the field header. - */ - public void buildFieldHeader(XMLNode node) { - if (currentClass.serializableFields().length > 0) { - buildFieldSerializationOverview(currentClass); - fieldWriter.writeHeader(configuration.getText( - "doclet.Serialized_Form_fields")); - } - } - - /** - * If possible, build the serialization overview for the given - * class. - * - * @param classDoc the class to print the overview for. - */ - public void buildFieldSerializationOverview(ClassDoc classDoc) { - if (classDoc.definesSerializableFields()) { - FieldDoc serialPersistentField = - Util.asList(classDoc.serializableFields()).get(0); - // Check to see if there are inline comments, tags or deprecation - // information to be printed. - if (fieldWriter.shouldPrintOverview(serialPersistentField)) { - fieldWriter.writeHeader( - configuration.getText("doclet.Serialized_Form_class")); - fieldWriter.writeMemberDeprecatedInfo(serialPersistentField); - if (!configuration.nocomment) { - fieldWriter.writeMemberDescription(serialPersistentField); - fieldWriter.writeMemberTags(serialPersistentField); - } - // Footer required to close the definition list tag - // for serialization overview. - fieldWriter.writeFooter( - configuration.getText("doclet.Serialized_Form_class")); - } - } - } - - /** - * Build the field sub header. - */ - public void buildFieldSubHeader(XMLNode node) { - if (! currentClass.definesSerializableFields() ){ - FieldDoc field = (FieldDoc) currentMember; - fieldWriter.writeMemberHeader(field.type().asClassDoc(), - field.type().typeName(), field.type().dimension(), field.name()); - } - } - - /** - * Build the field deprecation information. - */ - public void buildFieldDeprecationInfo(XMLNode node) { - if (!currentClass.definesSerializableFields()) { - FieldDoc field = (FieldDoc)currentMember; - fieldWriter.writeMemberDeprecatedInfo(field); - } - } - - /** - * Build the field information. - */ - public void buildFieldInfo(XMLNode node) { - if(configuration.nocomment){ - return; - } - FieldDoc field = (FieldDoc)currentMember; - ClassDoc cd = field.containingClass(); - if (cd.definesSerializableFields()) { - // Process Serializable Fields specified as array of - // ObjectStreamFields. Print a member for each serialField tag. - // (There should be one serialField tag per ObjectStreamField - // element.) - SerialFieldTag[] tags = field.serialFieldTags(); - Arrays.sort(tags); - for (int i = 0; i < tags.length; i++) { - fieldWriter.writeMemberHeader(tags[i].fieldTypeDoc(), - tags[i].fieldType(), "", tags[i].fieldName()); - fieldWriter.writeMemberDescription(tags[i]); - - } - } else { - - // Process default Serializable field. - if ((field.tags("serial").length == 0) && ! field.isSynthetic() - && configuration.serialwarn) { - configuration.message.warning(field.position(), - "doclet.MissingSerialTag", cd.qualifiedName(), - field.name()); - } - fieldWriter.writeMemberDescription(field); - fieldWriter.writeMemberTags(field); - } - } - - /** - * Build the field sub footer. - */ - public void buildFieldSubFooter(XMLNode node) { - if (! currentClass.definesSerializableFields()) { - fieldWriter.writeMemberFooter(); - } - } - - /** - * Build the summaries for the methods that belong to the given - * class. - */ - public void buildSerializableMethods(XMLNode node) { - MemberDoc[] members = currentClass.serializationMethods(); - if (members.length > 0) { - for (int i = 0; i < members.length; i++) { - currentMember = members[i]; - buildChildren(node); - } - } - } - - /** - * Build the summaries for the fields that belong to the given - * class. - */ - public void buildSerializableFields(XMLNode node) { - MemberDoc[] members = currentClass.serializableFields(); - if (members.length > 0) { - for (int i = 0; i < members.length; i++) { - currentMember = members[i]; - buildChildren(node); - } - } - } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml index 2be5de4bad2..d6588aaef1b 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml @@ -29,177 +29,144 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - + + + + + + - + - -
    - - - - - - - - - - - - - - - - - - - -