diff --git a/pom.xml b/pom.xml index de10428..f3fcac3 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ org.sonatype.nexus.plugins nexus-plugins - 2.11.2-06 + 2.11.3-01 @@ -67,6 +67,13 @@ ${nexus.version} provided + + org.sonatype.nexus.plugins + nexus-capabilities-plugin + ${nexus-plugin.type} + ${nexus.version} + provided + org.sonatype.nexus nexus-plugin-testsupport @@ -136,6 +143,11 @@ jackson-jaxrs 1.9.13 + + org.codehaus.jackson + jackson-mapper-asl + 1.9.13 + org.sonatype.nexus nexus-client-core diff --git a/replication-plugin.xml b/replication-plugin.xml index 6c34fa2..80be65d 100644 --- a/replication-plugin.xml +++ b/replication-plugin.xml @@ -18,7 +18,10 @@ requestsQueueSize and requestsSendingThreadsCount attributes define thread pool requests from master to peers asynchronously. The default values are: 500 for requestsQueueSize and 1 for requestsSendingThreadsCount --> - + http://localhost:8083/nexus diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapabilitiesBooter.java b/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapabilitiesBooter.java new file mode 100644 index 0000000..a7506fd --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapabilitiesBooter.java @@ -0,0 +1,30 @@ +package com.griddynamics.cd.nrp.internal.capabilities; + +import javax.inject.Named; + +import org.sonatype.nexus.plugins.capabilities.CapabilityRegistry; +import org.sonatype.nexus.plugins.capabilities.support.CapabilityBooterSupport; + +import org.eclipse.sisu.EagerSingleton; + +import java.util.Collections; + +@Named +@EagerSingleton +public class ReplicationPluginCapabilitiesBooter + extends CapabilityBooterSupport +{ + + @Override + protected void boot(final CapabilityRegistry registry) + throws Exception + { + maybeAddCapability( + registry, + ReplicationPluginCapabilityDescriptor.TYPE, + true, // enabled + null, // no notes + Collections.emptyMap()); + } + +} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapability.java b/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapability.java new file mode 100644 index 0000000..b18c43d --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapability.java @@ -0,0 +1,81 @@ +package com.griddynamics.cd.nrp.internal.capabilities; + +import com.griddynamics.cd.nrp.internal.model.config.ReplicationPluginConfigurationStorage; +import com.griddynamics.cd.nrp.internal.uploading.ArtifactUpdateApiClient; +import com.griddynamics.cd.nrp.internal.uploading.impl.ArtifactUpdateApiClientImpl; +import com.griddynamics.cd.nrp.internal.uploading.impl.factories.JerseyClientFactory; +import org.jetbrains.annotations.NonNls; +import org.sonatype.nexus.capability.support.CapabilitySupport; +import org.sonatype.nexus.plugins.capabilities.Condition; +import org.sonatype.nexus.plugins.capabilities.Evaluable; + +import javax.inject.Inject; +import javax.inject.Named; +import java.util.HashMap; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; + +@Named(ReplicationPluginCapabilityDescriptor.TYPE_ID) +public class ReplicationPluginCapability + extends CapabilitySupport { + @NonNls + public static final String NL = System.getProperty("line.separator"); + + private final ReplicationPluginConfigurationStorage gridRegistry; + private final ArtifactUpdateApiClientImpl artifactUpdateApiClient; + private final JerseyClientFactory jerseyClientFactory; + + @Inject + public ReplicationPluginCapability(ReplicationPluginConfigurationStorage replicationPluginConfigurationStorage, + ArtifactUpdateApiClientImpl artifactUpdateApiClient, + JerseyClientFactory jerseyClientFactory) { + this.gridRegistry = checkNotNull(replicationPluginConfigurationStorage); + this.artifactUpdateApiClient = artifactUpdateApiClient; + this.jerseyClientFactory = jerseyClientFactory; + } + + @Override + protected ReplicationPluginCapabilityConfiguration createConfig(final Map properties) throws Exception { + Map newProperties = new HashMap<>(properties); + return new ReplicationPluginCapabilityConfiguration(newProperties); + } + + @Override + public void configure(final ReplicationPluginCapabilityConfiguration config){ + gridRegistry.setMasterServerURLPrefix(config.getMasterServerURLPrefix()); + gridRegistry.setRequestQueueSize(config.getRequestQueueSize()); + gridRegistry.setRequestSendingThreadCount(config.getRequestSendingThreadCount()); + gridRegistry.setRequestQueueDumpFileName(config.getRequestQueueDumpFileName()); + gridRegistry.setServers(config.getNexusServers()); + jerseyClientFactory.onActivate(); + artifactUpdateApiClient.onActivate(); + } + + @Override + public Condition activationCondition() { + return conditions().capabilities().evaluable( + new Evaluable() { + @Override + public boolean isSatisfied() { + return true; + } + + @Override + public String explainSatisfied() { + return "\"createrepo\" and \"mergerepo\" are available"; + } + + @Override + public String explainUnsatisfied() { + return ""; + } + } + ); + } + + @Override + protected String renderStatus() { + return "Sample Nexus replication plugin status"; + } +} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapabilityConfiguration.java b/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapabilityConfiguration.java new file mode 100644 index 0000000..a9e772e --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapabilityConfiguration.java @@ -0,0 +1,95 @@ +package com.griddynamics.cd.nrp.internal.capabilities; + +import com.google.common.collect.Maps; +import com.griddynamics.cd.nrp.internal.model.config.ReplicationPluginConfigurationStorage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import static com.google.common.base.Strings.isNullOrEmpty; + +public class ReplicationPluginCapabilityConfiguration { + + public static final String MASTER_SERVER_URL_PREFIX = "myUrl"; + public static final String REQUESTS_QUEUE_SIZE = "requestsQueueSize"; + public static final String REQUESTS_SENDING_THREADS_COUNT = "requestsSendingThreadsCount"; + public static final String QUEUE_DUMP_FILE_NAME = "queueDumpFileName"; + public static final String SERVER_URL = "server_url"; + public static final String SERVER_LOGIN = "server_user"; + public static final String SERVER_PASSWORD = "server_password"; + + private final String masterServerURLPrefix; + private final int requestQueueSize; + private final int requestSendingThreadCount; + private final String requestQueueDumpFileName; + private final Set nexusServers; + Logger logger = + LoggerFactory.getLogger(ReplicationPluginCapabilityConfiguration.class); + + public ReplicationPluginCapabilityConfiguration(final Map properties) { + this.masterServerURLPrefix = properties.get(MASTER_SERVER_URL_PREFIX); + this.requestQueueSize = Integer.parseInt(properties.get(REQUESTS_QUEUE_SIZE)); + this.requestSendingThreadCount = Integer.parseInt(properties.get(REQUESTS_SENDING_THREADS_COUNT)); + this.requestQueueDumpFileName = properties.get(QUEUE_DUMP_FILE_NAME); + this.nexusServers = new LinkedHashSet<>(); + + for (int i = 0; i < 5; i++) { + String serverUrl = properties.get(SERVER_URL + "_" + i); + String serverLogin = properties.get(SERVER_LOGIN + "_" + i); + String serverPassword = properties.get(SERVER_PASSWORD + "_" + i); + + if (isNullOrEmpty(serverUrl) || + isNullOrEmpty(serverLogin) || + isNullOrEmpty(serverPassword)) { + continue; + } + + ReplicationPluginConfigurationStorage.NexusServer nexusServer = new ReplicationPluginConfigurationStorage.NexusServer( + serverUrl, + serverLogin, + serverPassword + ); + nexusServers.add(nexusServer); + } + } + + public Map asMap() { + final Map props = Maps.newHashMap(); + props.put(MASTER_SERVER_URL_PREFIX, masterServerURLPrefix); + props.put(REQUESTS_QUEUE_SIZE, String.valueOf(requestQueueSize)); + props.put(REQUESTS_SENDING_THREADS_COUNT, String.valueOf(requestSendingThreadCount)); + props.put(QUEUE_DUMP_FILE_NAME, requestQueueDumpFileName); + Iterator nexusServerIterator = nexusServers.iterator(); + for (int i = 0; nexusServerIterator.hasNext(); i++) { + ReplicationPluginConfigurationStorage.NexusServer nexusServer = nexusServerIterator.next(); + props.put(SERVER_URL + "_" + i, nexusServer.getUrl()); + props.put(SERVER_LOGIN + "_" + i, nexusServer.getUser()); + props.put(SERVER_PASSWORD + "_" + i, nexusServer.getPassword()); + } + return props; + } + + public String getMasterServerURLPrefix() { + return masterServerURLPrefix; + } + + public int getRequestQueueSize() { + return requestQueueSize; + } + + public int getRequestSendingThreadCount() { + return requestSendingThreadCount; + } + + public String getRequestQueueDumpFileName() { + return requestQueueDumpFileName; + } + + public Set getNexusServers() { + return nexusServers; + } +} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapabilityDescriptor.java b/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapabilityDescriptor.java new file mode 100644 index 0000000..80ed3bb --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/capabilities/ReplicationPluginCapabilityDescriptor.java @@ -0,0 +1,170 @@ +package com.griddynamics.cd.nrp.internal.capabilities; + +import org.sonatype.nexus.capability.support.CapabilityDescriptorSupport; +import org.sonatype.nexus.formfields.FormField; +import org.sonatype.nexus.formfields.NumberTextFormField; +import org.sonatype.nexus.formfields.PasswordFormField; +import org.sonatype.nexus.formfields.StringTextFormField; +import org.sonatype.nexus.plugins.capabilities.*; +import org.sonatype.nexus.plugins.capabilities.support.validator.Validators; +import org.sonatype.sisu.goodies.i18n.I18N; +import org.sonatype.sisu.goodies.i18n.MessageBundle; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static org.sonatype.nexus.plugins.capabilities.CapabilityType.capabilityType; +import static org.sonatype.nexus.plugins.capabilities.Tag.categoryTag; +import static org.sonatype.nexus.plugins.capabilities.Tag.tags; + +@Singleton +@Named(ReplicationPluginCapabilityDescriptor.TYPE_ID) +public class ReplicationPluginCapabilityDescriptor + extends CapabilityDescriptorSupport + implements Taggable { + public static final String TYPE_ID = "nexus-replication-plugin"; + + public static final CapabilityType TYPE = capabilityType(TYPE_ID); + private static final Messages messages = I18N.create(Messages.class); + private final Validators validators; + private final List formFields; + + @Inject + public ReplicationPluginCapabilityDescriptor(final Validators validators) { + this.validators = validators; + + List formFields = new ArrayList<>(); + formFields.add(new StringTextFormField( + ReplicationPluginCapabilityConfiguration.MASTER_SERVER_URL_PREFIX, + messages.masterServerURLPrefixLabel(), + messages.masterServerURLPrefixHelp(), + FormField.OPTIONAL + ).withInitialValue("http://localhost:8081/nexus")); + formFields.add(new NumberTextFormField(ReplicationPluginCapabilityConfiguration.REQUESTS_QUEUE_SIZE, + messages.requestQueueSizeLabel(), + messages.requestQueueSizeHelp(), + FormField.OPTIONAL + ).withInitialValue(500)); + formFields.add(new NumberTextFormField( + ReplicationPluginCapabilityConfiguration.REQUESTS_SENDING_THREADS_COUNT, + messages.requestSendingThreadCountLabel(), + messages.requestSendingThreadCountHelp(), + FormField.OPTIONAL + ).withInitialValue(1)); + formFields.add(new StringTextFormField( + ReplicationPluginCapabilityConfiguration.QUEUE_DUMP_FILE_NAME, + messages.requestQueueDumpFileNameLabel(), + messages.requestQueueDumpFileNameHelp(), + FormField.OPTIONAL + ).withInitialValue("/tmp/nexus-replication-plugin-queue-backup")); + + for (int i = 0; i < 5; i++) { + formFields.add(new StringTextFormField( + ReplicationPluginCapabilityConfiguration.SERVER_URL + "_" + i, + messages.serverUrlLabel() + " (Instance nr " + (i + 1) + ")", + messages.serverUrlHelp(), + FormField.OPTIONAL + ).withInitialValue("")); + formFields.add(new StringTextFormField( + ReplicationPluginCapabilityConfiguration.SERVER_LOGIN + "_" + i, + messages.serverLoginLabel() + " (Instance nr " + (i + 1) + ")", + messages.serverLoginHelp(), + FormField.OPTIONAL + ).withInitialValue("")); + formFields.add(new PasswordFormField( + ReplicationPluginCapabilityConfiguration.SERVER_PASSWORD + "_" + i, + messages.serverPasswordLabel() + " (Instance nr " + (i + 1) + ")", + messages.serverPasswordHelp(), + FormField.OPTIONAL + ).withInitialValue("")); + } + this.formFields = formFields; + } + + @Override + public Validator validator() { + return validators.logical().and( + validators.capability().uniquePer(TYPE) + ); + } + + @Override + public Validator validator(final CapabilityIdentity id) { + return validators.logical().and( + validators.capability().uniquePerExcluding(id, TYPE) + ); + } + + @Override + public CapabilityType type() { + return TYPE; + } + + @Override + public String name() { + return messages.name(); + } + + @Override + public List formFields() { + return formFields; + } + + @Override + public Set getTags() { + return tags(categoryTag("Grid")); + } + + private static interface Messages + extends MessageBundle { + @DefaultMessage("Nexus Replication Plugin Configuration") + String name(); + + @DefaultMessage("Master server's URL prefix") + String masterServerURLPrefixLabel(); + + @DefaultMessage("Master server's URL prefix (e.g. http://localhost:8081/nexus") + String masterServerURLPrefixHelp(); + + @DefaultMessage("Request queue size") + String requestQueueSizeLabel(); + + @DefaultMessage("Request queue size (default 500)") + String requestQueueSizeHelp(); + + @DefaultMessage("Request sending thread count") + String requestSendingThreadCountLabel(); + + @DefaultMessage("Request sending thread count (default 1)") + String requestSendingThreadCountHelp(); + + @DefaultMessage("Request queue dump file") + String requestQueueDumpFileNameLabel(); + + @DefaultMessage("Request queue dump file (default /tmp/nexus-replication-plugin-queue-backup)") + String requestQueueDumpFileNameHelp(); + + @DefaultMessage("Peer server's url") + String serverUrlLabel(); + + @DefaultMessage("Peer server's url (like http://localhost:8083/nexus)") + String serverUrlHelp(); + + @DefaultMessage("Peer server's login") + String serverLoginLabel(); + + @DefaultMessage("Peer server's login (default: admin)") + String serverLoginHelp(); + + @DefaultMessage("Peer server's password") + String serverPasswordLabel(); + + @DefaultMessage("Peer server's password (default: admin123") + String serverPasswordHelp(); + + } +} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/model/config/NexusServer.java b/src/main/java/com/griddynamics/cd/nrp/internal/model/config/NexusServer.java deleted file mode 100644 index a479160..0000000 --- a/src/main/java/com/griddynamics/cd/nrp/internal/model/config/NexusServer.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2015, Grid Dynamics International, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.griddynamics.cd.nrp.internal.model.config; - -import lombok.*; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; - -/** - * DTO Class encapsulates replication nexus server api access configuration - */ -@NoArgsConstructor -@RequiredArgsConstructor -@XmlAccessorType(XmlAccessType.FIELD) -public class NexusServer { - @Getter - @NonNull - @XmlElement(name = "url") - private String url; - @Getter - @NonNull - @XmlElement(name = "user") - private String user; - @Getter - @NonNull - @XmlElement(name = "password") - private String password; -} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/model/config/ReplicationPluginConfiguration.java b/src/main/java/com/griddynamics/cd/nrp/internal/model/config/ReplicationPluginConfiguration.java deleted file mode 100644 index 47a4feb..0000000 --- a/src/main/java/com/griddynamics/cd/nrp/internal/model/config/ReplicationPluginConfiguration.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2015, Grid Dynamics International, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.griddynamics.cd.nrp.internal.model.config; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; -import javax.xml.bind.annotation.XmlRootElement; -import java.util.HashSet; -import java.util.Set; - -/** - * DTO Class encapsulates replication plugin configurations - */ -@NoArgsConstructor -@RequiredArgsConstructor -@XmlRootElement(name = "configurations") -public class ReplicationPluginConfiguration { - @XmlElement(name = "server") - @XmlElementWrapper(name = "servers") - private final Set servers = new HashSet<>(); - @Getter - @NonNull - @XmlAttribute(name = "myUrl") - private String myUrl; - @XmlAttribute(name = "requestsQueueSize") - private Integer requestsQueueSize = 500; - @XmlAttribute(name = "requestsSendingThreadsCount") - private Integer requestsSendingThreadsCount = 1; - @XmlAttribute(name = "queueDumpFileName") - private String queueDumpFileName; - - public void addServer(NexusServer server) { - servers.add(server); - } - - public Integer getRequestsQueueSize() { - return requestsQueueSize; - } - - public String getQueueDumpFileName() { - return queueDumpFileName; - } - - public Integer getRequestsSendingThreadsCount() { - return requestsSendingThreadsCount; - } - - public Set getServers() { - return servers; - } -} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/model/config/ReplicationPluginConfigurationStorage.java b/src/main/java/com/griddynamics/cd/nrp/internal/model/config/ReplicationPluginConfigurationStorage.java new file mode 100644 index 0000000..95ba3fb --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/model/config/ReplicationPluginConfigurationStorage.java @@ -0,0 +1,137 @@ +package com.griddynamics.cd.nrp.internal.model.config; + +import lombok.NoArgsConstructor; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.ToString; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; +import java.util.LinkedHashSet; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * DTO Class for storing plugin's configuration: + * - master server URL prefix + * - request queue size + * - request sending thread count + * - request queue backup file + * - peer servers + *

+ * At first run, the default configuration is being created by ReplicationPluginCapabilitiesBooter, and passed to this class + *

+ * Then every time Nexus is being restarted or plugin's settings changed, ReplicationPluginCapability passes new settings to this class + */ + +@Named(value = "replicationPluginConfigurationStorage") +@Singleton +public class ReplicationPluginConfigurationStorage { + + Logger logger = + LoggerFactory.getLogger(ReplicationPluginConfigurationStorage.class); + + private volatile String masterServerURLPrefix = null; + private volatile Integer requestQueueSize = null; + private volatile Integer requestSendingThreadCount = null; + private volatile String requestQueueDumpFileName = null; + private volatile Set servers = null; + + @Inject + public ReplicationPluginConfigurationStorage() { + } + + public String getMasterServerURLPrefix() { + checkNotNull(masterServerURLPrefix, "Replication plugin configuration not ready yet!"); + return this.masterServerURLPrefix; + } + + public void setMasterServerURLPrefix(String masterServerURLPrefix) { + checkNotNull(masterServerURLPrefix, "Replication plugin configuration parameter cannot be set to null"); + this.masterServerURLPrefix = masterServerURLPrefix; + logger.info(toString()); + } + + public String getRequestQueueDumpFileName() { + checkNotNull(requestQueueDumpFileName, "Replication plugin configuration not ready yet!"); + return requestQueueDumpFileName; + } + + public void setRequestQueueDumpFileName(String requestQueueDumpFileName) { + checkNotNull(requestQueueDumpFileName, "Replication plugin configuration parameter cannot be set to null"); + this.requestQueueDumpFileName = requestQueueDumpFileName; + logger.info(toString()); + } + + public Set getServers() { + checkNotNull(servers, "Replication plugin configuration not ready yet!"); + return servers; + } + + public void setServers(Set nexusServers) { + checkNotNull(nexusServers, "Replication plugin configuration parameter cannot be set to null"); + servers = new LinkedHashSet<>(nexusServers); + logger.info(toString()); + } + + public int getRequestSendingThreadCount() { + checkNotNull(requestSendingThreadCount, "Replication plugin configuration not ready yet!"); + return requestSendingThreadCount; + } + + public void setRequestSendingThreadCount(Integer requestSendingThreadCount) { + checkNotNull(requestSendingThreadCount, "Replication plugin configuration parameter cannot be set to null"); + this.requestSendingThreadCount = requestSendingThreadCount; + logger.info(toString()); + } + + public int getRequestQueueSize() { + checkNotNull(requestQueueSize, "Replication plugin configuration not ready yet!"); + return requestQueueSize; + } + + public void setRequestQueueSize(Integer requestQueueSize) { + checkNotNull(requestQueueSize, "Replication plugin configuration parameter cannot be set to null"); + this.requestQueueSize = requestQueueSize; + logger.info(toString()); + } + + @Override + public String toString() { + return "ReplicationPluginConfigurationStorage{" + + "masterServerURLPrefix='" + masterServerURLPrefix + '\'' + + ", requestQueueSize=" + requestQueueSize + + ", requestSendingThreadCount=" + requestSendingThreadCount + + ", requestQueueDumpFileName='" + requestQueueDumpFileName + '\'' + + ", servers=" + servers + + '}'; + } + + @NoArgsConstructor + @RequiredArgsConstructor + @ToString + public static class NexusServer { + @NonNull + private String url; + @NonNull + private String user; + @NonNull + private String password; + + public String getUrl() { + return url; + } + + public String getUser() { + return user; + } + + public String getPassword() { + return password; + } + } +} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/model/internal/ArtifactMetaInfoQueueDump.java b/src/main/java/com/griddynamics/cd/nrp/internal/model/internal/ArtifactMetaInfoQueueDump.java deleted file mode 100644 index e635f42..0000000 --- a/src/main/java/com/griddynamics/cd/nrp/internal/model/internal/ArtifactMetaInfoQueueDump.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2015, Grid Dynamics International, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.griddynamics.cd.nrp.internal.model.internal; - -import com.griddynamics.cd.nrp.internal.model.api.ArtifactMetaInfo; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; -import javax.xml.bind.annotation.XmlRootElement; -import java.util.HashSet; -import java.util.Set; - -/** - * DTO Class encapsulates artifact replication queue - */ -@XmlRootElement(name = "artifactMetaInfoBlockingQueueDump") -public class ArtifactMetaInfoQueueDump { - @XmlElement(name = "artifactMetaInfo") - @XmlElementWrapper(name = "artifactMetaInfos") - private final Set artifactMetaInfos = new HashSet<>(); - - public void addArtifactMetaInfo(ArtifactMetaInfo artifactMetaInfo) { - artifactMetaInfos.add(artifactMetaInfo); - } - public void addAllArtifactMetaInfo(Set artifactMetaInfo) { - artifactMetaInfos.addAll(artifactMetaInfo); - } - - public Set getArtifactMetaInfos() { - return artifactMetaInfos; - } - -} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/ConfigurationsManager.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/ConfigurationsManager.java deleted file mode 100644 index 17f9c4a..0000000 --- a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/ConfigurationsManager.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2015, Grid Dynamics International, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.griddynamics.cd.nrp.internal.uploading; - -import com.griddynamics.cd.nrp.internal.model.config.ReplicationPluginConfiguration; - -public interface ConfigurationsManager { - ReplicationPluginConfiguration getConfiguration(); -} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImpl.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImpl.java index 95b8551..d10b912 100644 --- a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImpl.java +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ArtifactUpdateApiClientImpl.java @@ -15,27 +15,20 @@ */ package com.griddynamics.cd.nrp.internal.uploading.impl; +import com.griddynamics.cd.nrp.internal.model.config.ReplicationPluginConfigurationStorage; import com.griddynamics.cd.nrp.internal.model.api.ArtifactMetaInfo; -import com.griddynamics.cd.nrp.internal.model.config.ReplicationPluginConfiguration; -import com.griddynamics.cd.nrp.internal.model.internal.ArtifactMetaInfoQueueDump; import com.griddynamics.cd.nrp.internal.model.api.RestResponse; -import com.griddynamics.cd.nrp.internal.model.config.NexusServer; import com.griddynamics.cd.nrp.internal.uploading.ArtifactUpdateApiClient; -import com.griddynamics.cd.nrp.internal.uploading.ConfigurationsManager; +import com.griddynamics.cd.nrp.internal.uploading.impl.factories.AsyncWebResourceBuilderFactory; +import com.griddynamics.cd.nrp.internal.uploading.impl.factories.FileBlockingQueueFactory; import com.sun.jersey.api.client.AsyncWebResource; -import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.GenericType; import com.sun.jersey.api.client.async.ITypeListener; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; import org.sonatype.sisu.goodies.common.ComponentSupport; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriBuilder; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import java.io.File; @@ -62,34 +55,31 @@ public class ArtifactUpdateApiClientImpl extends ComponentSupport implements Art */ public static final int QUEUE_TIMEOUT_IN_SECOND = 1; - /** - * Provides access to the plugin configurations - */ - private final ConfigurationsManager configurationsManager; - + private final FileBlockingQueueFactory fileBlockingQueueFactory; + private final AsyncWebResourceBuilderFactory asyncWebResourceBuilderFactory; + private final ReplicationPluginConfigurationStorage replicationPluginConfigurationStorage; /** * ExecutorService shares between clients. All treads are created in the same executor */ - private final ExecutorService jerseyHttpClientExecutor; - private final FileBlockingQueue fileBlockingQueue; + private FileBlockingQueue fileBlockingQueue; @Inject - public ArtifactUpdateApiClientImpl(ConfigurationsManager configurationsManager) { - this.configurationsManager = configurationsManager; - this.fileBlockingQueue = initFileBlockingQueue(configurationsManager.getConfiguration()); - this.jerseyHttpClientExecutor = new ThreadPoolExecutor( - configurationsManager.getConfiguration().getRequestsSendingThreadsCount(), - configurationsManager.getConfiguration().getRequestsSendingThreadsCount(), - 30, - TimeUnit.SECONDS, - new LinkedBlockingQueue( - configurationsManager.getConfiguration().getRequestsQueueSize()) - ); - initBackgroundWorkers(configurationsManager.getConfiguration()); + public ArtifactUpdateApiClientImpl(FileBlockingQueueFactory fileBlockingQueueFactory, + AsyncWebResourceBuilderFactory asyncWebResourceBuilderFactory, + ReplicationPluginConfigurationStorage replicationPluginConfigurationStorage) { + this.fileBlockingQueueFactory = fileBlockingQueueFactory; + this.asyncWebResourceBuilderFactory = asyncWebResourceBuilderFactory; + this.replicationPluginConfigurationStorage = replicationPluginConfigurationStorage; + } + + public void onActivate(){ + this.fileBlockingQueue = initFileBlockingQueue(replicationPluginConfigurationStorage); + initBackgroundWorkers(replicationPluginConfigurationStorage); } - private void initBackgroundWorkers(ReplicationPluginConfiguration replicationPluginConfiguration) { - int requestsSendingThreadsCount = replicationPluginConfiguration.getRequestsSendingThreadsCount(); + private void initBackgroundWorkers(ReplicationPluginConfigurationStorage replicationPluginConfigurationStorage) { + int requestsSendingThreadsCount = replicationPluginConfigurationStorage + .getRequestSendingThreadCount(); ExecutorService executorService = Executors.newFixedThreadPool(requestsSendingThreadsCount); for (int i = 0; i < requestsSendingThreadsCount; i++) { executorService.submit(new Runnable() { @@ -109,18 +99,15 @@ public void run() { } } - private FileBlockingQueue initFileBlockingQueue(ReplicationPluginConfiguration replicationPluginConfiguration) { - BlockingQueue blockingQueue = - new LinkedBlockingQueue<>(replicationPluginConfiguration.getRequestsQueueSize()); - String queueFileName = replicationPluginConfiguration.getQueueDumpFileName(); - FileBlockingQueue retVal = new FileBlockingQueue(blockingQueue, - queueFileName); + private FileBlockingQueue initFileBlockingQueue(ReplicationPluginConfigurationStorage replicationPluginConfigurationStorage) { + String queueFileName = replicationPluginConfigurationStorage.getRequestQueueDumpFileName(); + FileBlockingQueue retVal = fileBlockingQueueFactory.getFileBlockingQueue(); try { File queueFile = new File(queueFileName); if (queueFile.exists()) { - JAXBContext jaxbContext = JAXBContext.newInstance(ArtifactMetaInfoQueueDump.class); + JAXBContext jaxbContext = JAXBContext.newInstance(FileBlockingQueue.ArtifactMetaInfoQueueDump.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - ArtifactMetaInfoQueueDump unmarshal = (ArtifactMetaInfoQueueDump) unmarshaller.unmarshal(queueFile); + FileBlockingQueue.ArtifactMetaInfoQueueDump unmarshal = (FileBlockingQueue.ArtifactMetaInfoQueueDump) unmarshaller.unmarshal(queueFile); for (ArtifactMetaInfo artifactMetaInfo : unmarshal.getArtifactMetaInfos()) { offerRequest(artifactMetaInfo); } @@ -146,8 +133,10 @@ public void offerRequest(ArtifactMetaInfo artifactMetaInfo) { * @param metaInfo Artifact information */ public void sendRequest(ArtifactMetaInfo metaInfo) { - for (NexusServer server : configurationsManager.getConfiguration().getServers()) { - AsyncWebResource.Builder service = getService(server.getUrl(), server.getUser(), server.getPassword()); + for (ReplicationPluginConfigurationStorage.NexusServer server : replicationPluginConfigurationStorage.getServers()) { + AsyncWebResource.Builder service = + asyncWebResourceBuilderFactory.getAsyncWebResourceBuilder( + server.getUrl(), server.getUser(), server.getPassword()); try { service.post(new ITypeListener() { @Override @@ -180,42 +169,4 @@ public GenericType getGenericType() { } } - /** - * Returns jersey HTTP resource to access to the remote replication servers - * - * @param nexusUrl URL of the remote server - * @param login Username on the remote server - * @param password User's password - * @return Jersey HTTP client - */ - private AsyncWebResource.Builder getService(String nexusUrl, String login, String password) { - Client client = getClient(login, password); - client.setExecutorService(jerseyHttpClientExecutor); - AsyncWebResource webResource = client.asyncResource(UriBuilder.fromUri(nexusUrl).build()); - webResource = webResource.path("service").path("local").path("artifact").path("maven").path("update"); - return webResource.accept(MediaType.APPLICATION_XML_TYPE) - .type(MediaType.APPLICATION_XML_TYPE); - } - - /** - * Creates jersey HTTP client - * - * @param login Username on the remote server - * @param password User's password - * @return HTTP client - */ - private Client getClient(String login, String password) { - ClientConfig config = new DefaultClientConfig(); - config.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, 1000); - config.getProperties().put(ClientConfig.PROPERTY_READ_TIMEOUT, 2000); - Client client = Client.create(config); - client.setExecutorService(jerseyHttpClientExecutor); - if (login != null && !login.isEmpty() && password != null) { - log.debug("Creating HTTP client with authorized HTTPBasicAuthFilter."); - client.addFilter(new HTTPBasicAuthFilter(login, password)); - } else { - log.debug("Creating HTTP client with anonymous HTTPBasicAuthFilter."); - } - return client; - } } diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImpl.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImpl.java deleted file mode 100644 index 5d4b4be..0000000 --- a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/ConfigurationsManagerImpl.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2015, Grid Dynamics International, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.griddynamics.cd.nrp.internal.uploading.impl; - -import com.griddynamics.cd.nrp.internal.model.config.ReplicationPluginConfiguration; -import com.griddynamics.cd.nrp.internal.uploading.ConfigurationsManager; -import org.sonatype.nexus.configuration.application.NexusConfiguration; -import org.sonatype.sisu.goodies.common.ComponentSupport; - -import javax.annotation.PostConstruct; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import java.io.File; - -/** - * Class provides access to plugin configurations - * parsed from {@link ConfigurationsManagerImpl#CONFIG_FILENAME} file - */ -@Singleton -@Named(value = ConfigurationsManagerImpl.ID) -public class ConfigurationsManagerImpl extends ComponentSupport implements ConfigurationsManager { - - public static final String ID = "configurationsManager"; - - /** - * Filename of the XML configuration file - */ - private static final String CONFIG_FILENAME = "replication-plugin.xml"; - - /** - * Bean provides nexus server configurations - */ - private NexusConfiguration nexusConfiguration; - - /** - * DTO contains plugin configurations - */ - private volatile ReplicationPluginConfiguration config; - - @Inject - public ConfigurationsManagerImpl(NexusConfiguration nexusConfiguration) { - this.nexusConfiguration = nexusConfiguration; - } - - /** - * Loads configurations - * from {@link ConfigurationsManagerImpl#CONFIG_FILENAME} file - */ - @PostConstruct - public void init() { - log.trace("Initializing plugin configurations"); - reloadConfigurations(); - } - - /** - * Provides access to plugin configurations DTO - * @return Plugin configurations - */ - @Override - public ReplicationPluginConfiguration getConfiguration() { - if (config == null) { - synchronized (this) { - if (config == null) { - reloadConfigurations(); - } - } - } - return config; - } - - /** - * Reloads {@link ConfigurationsManagerImpl#config} - * from XML plugin configurations file - */ - public void reloadConfigurations() { - File file = getConfigurationFile(); - try { - JAXBContext jaxbContext = JAXBContext.newInstance(ReplicationPluginConfiguration.class); - - Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - config = (ReplicationPluginConfiguration) jaxbUnmarshaller.unmarshal(file); - } catch (JAXBException e) { - log.error("Can not deserialize xml configuration file: " + file.getAbsolutePath(), e); - } - } - - /** - * Returns plugin configurations XML file - */ - private File getConfigurationFile() { - return new File(nexusConfiguration.getConfigurationDirectory(), CONFIG_FILENAME); - } -} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/FileBlockingQueue.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/FileBlockingQueue.java index d2ea55b..4be9eed 100644 --- a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/FileBlockingQueue.java +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/FileBlockingQueue.java @@ -2,14 +2,18 @@ import com.google.common.collect.Sets; import com.griddynamics.cd.nrp.internal.model.api.ArtifactMetaInfo; -import com.griddynamics.cd.nrp.internal.model.internal.ArtifactMetaInfoQueueDump; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; import java.io.File; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; @@ -81,4 +85,25 @@ private synchronized void saveQueueToFile() { } + /** + * DTO Class encapsulates artifact replication queue + */ + @XmlRootElement(name = "artifactMetaInfoBlockingQueueDump") + public static class ArtifactMetaInfoQueueDump { + @XmlElement(name = "artifactMetaInfo") + @XmlElementWrapper(name = "artifactMetaInfos") + private final Set artifactMetaInfos = new HashSet<>(); + + public void addArtifactMetaInfo(ArtifactMetaInfo artifactMetaInfo) { + artifactMetaInfos.add(artifactMetaInfo); + } + public void addAllArtifactMetaInfo(Set artifactMetaInfo) { + artifactMetaInfos.addAll(artifactMetaInfo); + } + + public Set getArtifactMetaInfos() { + return artifactMetaInfos; + } + + } } diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/UploadEventListenerImpl.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/UploadEventListenerImpl.java index 8bad9be..ec1ddcc 100644 --- a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/UploadEventListenerImpl.java +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/UploadEventListenerImpl.java @@ -17,10 +17,10 @@ import com.google.common.eventbus.AllowConcurrentEvents; import com.google.common.eventbus.Subscribe; +import com.griddynamics.cd.nrp.internal.model.config.ReplicationPluginConfigurationStorage; import com.griddynamics.cd.nrp.internal.model.api.ArtifactMetaInfo; import com.griddynamics.cd.nrp.internal.model.api.ArtifactStatus; import com.griddynamics.cd.nrp.internal.uploading.ArtifactUpdateApiClient; -import com.griddynamics.cd.nrp.internal.uploading.ConfigurationsManager; import com.griddynamics.cd.nrp.internal.uploading.UploadEventListener; import org.sonatype.nexus.client.core.subsystem.repository.maven.MavenProxyRepository; import org.sonatype.nexus.proxy.events.RepositoryItemEventStore; @@ -46,17 +46,16 @@ public class UploadEventListenerImpl extends ComponentSupport implements UploadE /** * Provides access to plugin the configurations */ - private ConfigurationsManager configurationsManager; - - private ArtifactUpdateApiClient artifactUpdateApiClient; + private final ArtifactUpdateApiClient artifactUpdateApiClient; + private final ReplicationPluginConfigurationStorage replicationPluginConfigurationStorage; private Map receivedArtifacts = new ConcurrentHashMap<>(); @Inject - public UploadEventListenerImpl(@Named(value = ConfigurationsManagerImpl.ID) ConfigurationsManager configurationsManager, - @Named(value = ArtifactUpdateApiClientImpl.ID) ArtifactUpdateApiClient artifactUpdateApiClient) { - this.configurationsManager = configurationsManager; + public UploadEventListenerImpl(@Named(value = ArtifactUpdateApiClientImpl.ID) ArtifactUpdateApiClient artifactUpdateApiClient, + ReplicationPluginConfigurationStorage replicationPluginConfigurationStorage) { this.artifactUpdateApiClient = artifactUpdateApiClient; + this.replicationPluginConfigurationStorage = replicationPluginConfigurationStorage; } /** @@ -70,7 +69,12 @@ public void onArtifactUploading(RepositoryItemEventStore event) { MavenRepository repo = (MavenRepository) event.getRepository(); Gav gav = repo.getGavCalculator().pathToGav(event.getItemUid().getPath()); if (null != gav) { - ArtifactMetaInfo metaInfo = new ArtifactMetaInfo(configurationsManager.getConfiguration().getMyUrl(), gav.getGroupId(), gav.getArtifactId(), gav.getVersion(), repo.getId()); + ArtifactMetaInfo metaInfo = new ArtifactMetaInfo( + replicationPluginConfigurationStorage.getMasterServerURLPrefix(), + gav.getGroupId(), + gav.getArtifactId(), + gav.getVersion(), + repo.getId()); metaInfo.setClassifier(gav.getClassifier()); metaInfo.setExtension(gav.getExtension()); ArtifactStatus artifactStatus = null; diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/AsyncWebResourceBuilderFactory.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/AsyncWebResourceBuilderFactory.java new file mode 100644 index 0000000..aeec5ea --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/AsyncWebResourceBuilderFactory.java @@ -0,0 +1,38 @@ +package com.griddynamics.cd.nrp.internal.uploading.impl.factories; + +import com.sun.jersey.api.client.AsyncWebResource; +import com.sun.jersey.api.client.Client; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriBuilder; + +@Singleton +public class AsyncWebResourceBuilderFactory { + + private final JerseyClientFactory jerseyClientFactory; + + @Inject + public AsyncWebResourceBuilderFactory(JerseyClientFactory jerseyClientFactory) { + this.jerseyClientFactory = jerseyClientFactory; + } + + + /** + * Returns jersey HTTP resource to access to the remote replication servers + * + * @param nexusUrl URL of the remote server + * @param login Username on the remote server + * @param password User's password + * @return Jersey HTTP client + */ + public AsyncWebResource.Builder getAsyncWebResourceBuilder(String nexusUrl, String login, String password) { + Client client = jerseyClientFactory.getClient(login, password); + AsyncWebResource webResource = client.asyncResource(UriBuilder.fromUri(nexusUrl).build()); + webResource = webResource.path("service").path("local").path("artifact").path("maven").path("update"); + return webResource.accept(MediaType.APPLICATION_XML_TYPE) + .type(MediaType.APPLICATION_XML_TYPE); + } + +} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/FileBlockingQueueFactory.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/FileBlockingQueueFactory.java new file mode 100644 index 0000000..133a889 --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/FileBlockingQueueFactory.java @@ -0,0 +1,34 @@ +package com.griddynamics.cd.nrp.internal.uploading.impl.factories; + +import com.griddynamics.cd.nrp.internal.model.config.ReplicationPluginConfigurationStorage; +import com.griddynamics.cd.nrp.internal.model.api.ArtifactMetaInfo; +import com.griddynamics.cd.nrp.internal.uploading.impl.FileBlockingQueue; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +@Singleton +public class FileBlockingQueueFactory { + + private final ReplicationPluginConfigurationStorage + replicationPluginConfigurationStorage; + + @Inject + public FileBlockingQueueFactory(ReplicationPluginConfigurationStorage replicationPluginConfigurationStorage) { + this.replicationPluginConfigurationStorage = replicationPluginConfigurationStorage; + } + + public FileBlockingQueue getFileBlockingQueue() { + BlockingQueue blockingQueue = + new LinkedBlockingQueue<>( + replicationPluginConfigurationStorage.getRequestQueueSize()); + String blockingQueueDumpFileName = + replicationPluginConfigurationStorage.getRequestQueueDumpFileName(); + + return new FileBlockingQueue(blockingQueue, + blockingQueueDumpFileName); + } + +} diff --git a/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/JerseyClientFactory.java b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/JerseyClientFactory.java new file mode 100644 index 0000000..a3824bc --- /dev/null +++ b/src/main/java/com/griddynamics/cd/nrp/internal/uploading/impl/factories/JerseyClientFactory.java @@ -0,0 +1,67 @@ +package com.griddynamics.cd.nrp.internal.uploading.impl.factories; + +import com.griddynamics.cd.nrp.internal.model.config.ReplicationPluginConfigurationStorage; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.config.ClientConfig; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +@Singleton +public class JerseyClientFactory { + + private final ReplicationPluginConfigurationStorage + replicationPluginConfigurationStorage; + private Logger log = LoggerFactory.getLogger(JerseyClientFactory.class); + private ExecutorService executorService; + + @Inject + public JerseyClientFactory( + ReplicationPluginConfigurationStorage + replicationPluginConfigurationStorage) { + this.replicationPluginConfigurationStorage = replicationPluginConfigurationStorage; + + } + + public void onActivate() { + int requestQueueSize = replicationPluginConfigurationStorage.getRequestQueueSize(); + this.executorService = new ThreadPoolExecutor( + replicationPluginConfigurationStorage.getRequestSendingThreadCount(), + replicationPluginConfigurationStorage.getRequestSendingThreadCount(), + 30, + TimeUnit.SECONDS, + new LinkedBlockingQueue( + requestQueueSize)); + } + + /** + * @param login Login to Nexus + * @param password Password to Nexus + * @return Jersey Client for provide login and password with connection timeout set to 1000 ms and read timeout set to 2000 + * This particular values for timeouts were chosen to avoid potential deadlock in case of peer server load + */ + + public Client getClient(String login, String password) { + ClientConfig config = new DefaultClientConfig(); + config.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, 1000); + config.getProperties().put(ClientConfig.PROPERTY_READ_TIMEOUT, 2000); + Client client = Client.create(config); + client.setExecutorService(executorService); + if (login != null && !login.isEmpty() && password != null) { + log.debug("Creating HTTP client with authorized HTTPBasicAuthFilter."); + client.addFilter(new HTTPBasicAuthFilter(login, password)); + } else { + log.debug("Creating HTTP client with anonymous HTTPBasicAuthFilter."); + } + return client; + } + +}