[
https://issues.apache.org/jira/browse/RIVER-29?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16911840#comment-16911840
]
Peter Firmstone commented on RIVER-29:
--------------------------------------
Rather than using inheritance, which just exposes internal state, I recommend
that we use a Factory and ServiceProvider instead to allow customization of
MarshalledInstance.
For example:
/*
* TODO: ServiceProvider for MarshalFactory, to allow clients to use
* any Serialization framework for handback objects used in Jini api's,
* such as events. It isn't appropriate to use subclasses where
* remote service nodes use a prior version, or don't support dynamic
* class loading.
*
* Service proxy's wishing to utilise different Serialization Frameworks
* can subclass MarshalledInstance directly to provide their own implementation.
*/
/**
* Creates a new <code>MarshalledInstance</code> that contains the
* marshalled representation of the current state of the supplied
* object. The object is serialized with the semantics defined by
* <code>MarshalOutput</code>.
*
* This is designed to allow MarshalledInstance to be extensible
* and utilize other Serialization Frameworks.
*
* This constructor calls a chain of internal constructors and static
* methods that prevent finalizer attacks.
*
* It is advisable for overriding classes to be stateless.
*
* @param obj The Object to be contained in the new
* <code>MarshalledInstance</code>
* @param context the collection of context information objects or
* <code>null</code>
* @param marshalFactory MarshalFactory used to create underlying
MarshalInstanceInput
* and MarshalInstanceOutput.
* @throws IOException if the object cannot be serialized
* @throws NullPointerException if context or marshalFactory is null.
*/
protected MarshalledInstance(Object obj, Collection context, MarshalFactory
marshalFactory) throws IOException{
this(obj, context, marshalFactory,
obj != null ? new ByteArrayOutputStream() : null,
obj != null ? new ByteArrayOutputStream() : null);
}
private MarshalledInstance(Object obj, Collection context, MarshalFactory
factory, ByteArrayOutputStream bout,
ByteArrayOutputStream lout) throws IOException
{
this(bout,
obj != null ?
writeOutRetLocAnnotation(obj, context, factory, bout, lout)
: null
);
}
/**
*
* @param obj Object to be marshaled.
* @param context
* @param factory MarshalFactory used to create MarshalIntstanceOutput
* @param bout ByteArrayOutputStream to write object serial form.
* @param lout ByteArrayOutputStream to write code-base annotation to.
* @return byte array of location.
* @throws IOException
*/
private static byte[] writeOutRetLocAnnotation(Object obj, Collection context,
MarshalFactory factory,
ByteArrayOutputStream bout, ByteArrayOutputStream lout) throws IOException
{
if (context == null) throw new NullPointerException();
if (factory == null) throw new NullPointerException();
MarshalInstanceOutput out = null;
try {
out = factory.createMarshalOutput(bout, lout, context);
out.writeObject(obj);
out.flush();
// locBytes is null if no annotations
return out.hadAnnotations() ? lout.toByteArray() : null;
} finally {
try {
if (out != null) out.close();
} catch (IOException e){} // Ignore
}
}
/**
* Allows for alternative serialization implementations of MarshalledInstance.
*
* @author peter
*/
public interface MarshalFactory {
/**
*
* @param objIn InputStream to read serialized objects from.
* @param locIn InputStream to read codebase annotations from, optional.
*@param defaultLoader the class loader value (possibly
* <code>null</code>) to pass as the <code>defaultLoader</code>
* argument to <code>RMIClassLoader</code> methods
* @param verifyCodebaseIntegrity if <code>true</code> then
* codebase integrity is verified, otherwise code base
* integrity is not verified
* @param verifierLoader the class loader value (possibly
* <code>null</code>) to pass to {@link
* net.jini.security.Security#verifyCodebaseIntegrity
* Security.verifyCodebaseIntegrity}, if
* <code>verifyCodebaseIntegrity</code> is <code>true</code>
* @param context the collection of context information objects or
* <code>null</code>
* @return a new MarshalInstanceInput instance.
* @throws IOException if an
* <code>IOException</code> occurs while creating the
* MarshalInstanceInput.
*/
MarshalInstanceInput createMarshalInput(InputStream objIn,
InputStream locIn,
ClassLoader defaultLoader,
boolean verifyCodebaseIntegrity,
ClassLoader verifierLoader,
Collection context) throws IOException;
/**
*
* @param objOut the output stream to write objects to.
* @param locOut the output stream to write annotations to.
* @param context the collection of context information objects or
* <code>null</code>
* @return an instance of MarshalInstanceOutput
* @throws java.io.IOException if an
* <code>IOException</code> occurs while creating the
* MarshalInstanceOutput.
*/
MarshalInstanceOutput createMarshalOutput(OutputStream objOut, OutputStream
locOut, Collection context) throws IOException;
}
> Make some of the private fields of MarshalledInstance protected for the
> purpose of access by subclasses
> -------------------------------------------------------------------------------------------------------
>
> Key: RIVER-29
> URL: https://issues.apache.org/jira/browse/RIVER-29
> Project: River
> Issue Type: Wish
> Components: net_jini_io
> Affects Versions: jtsk_2.1
> Reporter: Mark Brouwer
> Priority: Minor
>
> {{net.jini.io.MarshalledInstance}} allows for subclassing but some of the
> fields that might be needed by a subclass can't be accessed as they are
> declared {{private}}. A subclass has to pass these in to the constructor of
> the superclass so must have 'access' to them. There seems to be no harm to
> make them {{protected}}, especially since they are {{final}}. See also this
> posting on the
> [river-dev|http://mail-archives.apache.org/mod_mbox/incubator-river-dev/200706.mbox/%[email protected]%3e]
> mailing list.
--
This message was sent by Atlassian Jira
(v8.3.2#803003)