0

I have found following piece of code on github:

public class DummySSLSocketFactory extends SSLSocketFactory {

    private static final Logger LOG = LoggerFactory.getLogger(DummySSLSocketFactory.class);
    private SSLSocketFactory factory;

    public DummySSLSocketFactory() {
        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            TrustManager[] trustManagers = new TrustManager[] {new DummyTrustManager()};
            sslContext.init(null, trustManagers, new java.security.SecureRandom());
            factory = sslContext.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeCamelException("Error creating DummySSLSocketFactory: " + e.getMessage(), e);
        }
    }

    /**
     * Must provide this getDefault operation for JavaMail to be able to use this factory.
     */
    public static SocketFactory getDefault() {
        LOG.warn("Camel is using DummySSLSocketFactory as SSLSocketFactory (only to be used for testing purpose)");
        return new DummySSLSocketFactory();
    }

    public String[] getDefaultCipherSuites() {
        return factory.getDefaultCipherSuites();
    }

    public String[] getSupportedCipherSuites() {
        return factory.getSupportedCipherSuites();
    }

    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
        return factory.createSocket(socket, host, port, autoClose);
    }

    public Socket createSocket(String host, int port) throws IOException {
        return factory.createSocket(host, port);
    }

    public Socket createSocket(String host, int port, InetAddress localAddress, int localPort)
        throws IOException {
        return factory.createSocket(host, port, localAddress, localPort);
    }

    public Socket createSocket(InetAddress host, int port) throws IOException {
        return factory.createSocket(host, port);
    }

    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
        throws IOException {
        return factory.createSocket(address, port, localAddress, localPort);
    }

    public Socket createSocket() throws IOException {
        // must have this createSocket method
        return factory.createSocket();
    }

}

Similar implementations are widely used across different projects. I tried to figure out what is the purpose of using both inheritance and composition at the same time. It looks like it would be enough just to have a factory method that returns the result of sslContext.getSocketFactory(); as it doesn't extend the class at all.

woockashek
  • 1,588
  • 10
  • 25
  • Maybe they couldn't just use a factory method because they're using some kind of reflection-based framework that requires a class with an accessible constructor, or maybe they needed to explicitly create a custom subclass of `SSLSocketFactory` for some reason. Or maybe they want to add logging capabilities to each method and they just haven't finished implementing the class. Hard to be sure in this particular instance. – Leo Aso Nov 20 '17 at 15:43

2 Answers2

1

I don't know what was the precise intent of who wrote this code, but in this organization of classes is clear that using both composition and inheritance, DummySSLSocketFactory can use protected methods implemented in SSLSocketFactory and even of the class above to it (using super).
This is possible because DummySSLSocketFactory has a reference to its parent class SSLSocketFactory

 private SSLSocketFactory factory;

set in DummySSLSocketFactory's costructor

factory = sslContext.getSocketFactory();

Without this reference you would be able to reach SSLSocketLayer using super, but not the class even higher.

Jul10
  • 503
  • 7
  • 19
  • This sounds quite reasonable. Now I see the benefit of combining composition and inheritance in one class so I'll accept your answer. – woockashek Nov 21 '17 at 14:17
  • don't you mean rather protected? As far as I know there's no way to access private members/methods in inherited class. – woockashek Nov 21 '17 at 14:22
  • Yes, you're right, I'll correct the answer. I meant that with composition you can point directly to the upper class SSLSocketFactory, in order to use some method in a specific implementation, that perhaps in Dummy is overriden. About members, I was wrong, I don't see any particular gain in doing that. – Jul10 Nov 21 '17 at 17:10
0

This is a common pattern (as you mentioned).

A child class can extend a Class (or implement an Interface) to establish a "is-a" relationship. In your example, DummySSLSocketFactory is-a SSLSocketFactory. An "is-a" relationship allows polymorphism.

The child class may not wish to fully override (or implement, in the case of an Interface) the methods, so it uses composition to get something that already overrides the uninteresting, but required, methods. To achieve this, the child class will forward calls to the "uninteresting" (my term there) methods to the composed member. In your example, the original class SSLSocketFactory provides the "default" implementation of stuff that is not interesting to the DummySSLSocketFactory class.

The forwarding of calls to the composed member is a variation of the Proxy pattern. It is not a full proxy, because it alters the functionality.

DwB
  • 37,124
  • 11
  • 56
  • 82
  • In this case I don't think we need to have composition. Instead of implementing proxy methods we could just skip implementing them – woockashek Nov 21 '17 at 14:14