Skip to content

Commit

Permalink
Merge pull request #124 from thomasgl-orange/JENKINS-47967
Browse files Browse the repository at this point in the history
[JENKINS-47967] workaround JCE Providers memory leak
  • Loading branch information
felfert committed Nov 13, 2017
2 parents c16b15c + 59dec96 commit 8d95930
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 4 deletions.
Expand Up @@ -54,7 +54,6 @@
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.domain.Location;
import org.jclouds.enterprise.config.EnterpriseConfigurationModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.providers.Providers;

Expand All @@ -72,6 +71,7 @@

import jenkins.plugins.jclouds.internal.CredentialsHelper;
import jenkins.plugins.jclouds.internal.LocationHelper;
import jenkins.plugins.jclouds.modules.JenkinsConfigurationModule;

/**
* Model class for Blobstore profile. User can configure multiple profiles to upload artifacts to different providers.
Expand Down Expand Up @@ -164,7 +164,7 @@ public String getLocationId() {
public org.jclouds.logging.Logger.LoggerFactory createLoggerFactory() {
return new BlobStoreLogger.Factory();
}
}, new EnterpriseConfigurationModule());
}, new JenkinsConfigurationModule());


private static BlobStoreContext ctx(final String provider, final String credId, final Properties overrides) {
Expand Down
Expand Up @@ -58,7 +58,6 @@
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.enterprise.config.EnterpriseConfigurationModule;
import org.jclouds.location.reference.LocationConstants;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.providers.Providers;
Expand Down Expand Up @@ -97,6 +96,7 @@

import jenkins.plugins.jclouds.internal.CredentialsHelper;
import jenkins.plugins.jclouds.internal.SSHPublicKeyExtractor;
import jenkins.plugins.jclouds.modules.JenkinsConfigurationModule;

import hudson.util.XStream2;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
Expand Down Expand Up @@ -271,7 +271,7 @@ public int getRetentionTime() {
public org.jclouds.logging.Logger.LoggerFactory createLoggerFactory() {
return new ComputeLogger.Factory();
}
}, new EnterpriseConfigurationModule());
}, new JenkinsConfigurationModule());

private static <A extends Closeable> A api(Class<A> apitype, final String provider, final String credId, final Properties overrides) {
// correct the classloader so that extensions can be found
Expand Down
@@ -0,0 +1,50 @@
package jenkins.plugins.jclouds.modules;

import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.security.cert.CertificateException;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.inject.Singleton;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jclouds.crypto.Crypto;
import org.jclouds.encryption.bouncycastle.BouncyCastleCrypto;
import org.jclouds.encryption.internal.JCECrypto;

/**
* A JCloud <code>{@link Crypto}</code> implementation, similar to <code>{@link BouncyCastleCrypto}</code>, but which
* always reuse the same <code>{@link BouncyCastleProvider}</code> instance, to avoid a memory leak.
*/
@Singleton
public class JenkinsBouncyCastleCrypto extends JCECrypto {

/* The only instance of BouncyCastleProvider we'll ever use in JClouds contexts.
* It may even be an already registered instance (Jenkins adds one on startup,
* when initializing the bouncycastle-api plugin). */
private static final BouncyCastleProvider BC_PROVIDER;
static {
final BouncyCastleProvider myBCProvider = new BouncyCastleProvider();
final Provider installedProvider = Security.getProvider(myBCProvider.getName());
if (installedProvider != null && installedProvider.getClass().equals(BouncyCastleProvider.class)) {
BC_PROVIDER = (BouncyCastleProvider) installedProvider;
} else {
BC_PROVIDER = myBCProvider;
}
}

public JenkinsBouncyCastleCrypto() throws NoSuchAlgorithmException, CertificateException {
super(BC_PROVIDER);
}

/**
* @see org.jclouds.encryption.bouncycastle.BouncyCastleCrypto
*/
@Override
public Cipher cipher(String algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException {
return super.cipher("RSA".equals(algorithm) ? "RSA/NONE/PKCS1Padding" : algorithm);
}

}
@@ -0,0 +1,25 @@
package jenkins.plugins.jclouds.modules;

import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.crypto.Crypto;
import org.jclouds.date.joda.config.JodaDateServiceModule;
import org.jclouds.netty.config.NettyPayloadModule;

/**
* Similar to <code>{@link org.jclouds.enterprise.config.EnterpriseConfigurationModule}</code>,
* but enables our own <code>JenkinsBouncyCastleCrypto</code> module instead of upstream's
* <code>BouncyCastleCrypto</code>. This is to avoid memory leak with new instances of
* <code>BouncyCastleProvider</code> getting registered each time a JClouds context is built.
*/
@ConfiguresExecutorService
public class JenkinsConfigurationModule extends ExecutorServiceModule {

@Override
protected void configure() {
bind(Crypto.class).to(JenkinsBouncyCastleCrypto.class);
install(new JodaDateServiceModule());
install(new NettyPayloadModule());
}

}

0 comments on commit 8d95930

Please sign in to comment.