[java-opensaml] 01/16: Initial work on converting a ProfileAction to a MessageHandler model.
Brent Putman
putmanb at georgetown.edu
Sun Dec 17 00:08:11 EST 2017
This is an automated email from the git hooks/post-receive script.
putmanb pushed a commit to branch master
in repository java-opensaml.
View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=7823083c8bb40b8f6a2745f3cc94f072ec65ffc7
commit 7823083c8bb40b8f6a2745f3cc94f072ec65ffc7
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Thu Aug 31 22:48:20 2017 -0400
Initial work on converting a ProfileAction to a MessageHandler model.
---
.../impl/PopulateSignatureSigningParameters.java | 84 ++++++--------
.../impl/PopulateSignatureSigningParameters.java | 126 ++++++++++-----------
.../PopulateSignatureSigningParametersTest.java | 4 +-
3 files changed, 97 insertions(+), 117 deletions(-)
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/profile/impl/PopulateSignatureSigningParameters.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/binding/impl/PopulateSignatureSigningParameters.java
similarity index 74%
copy from opensaml-saml-impl/src/main/java/org/opensaml/saml/common/profile/impl/PopulateSignatureSigningParameters.java
copy to opensaml-saml-impl/src/main/java/org/opensaml/saml/common/binding/impl/PopulateSignatureSigningParameters.java
index 32a9b96..86db169 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/profile/impl/PopulateSignatureSigningParameters.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/binding/impl/PopulateSignatureSigningParameters.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.opensaml.saml.common.profile.impl;
+package org.opensaml.saml.common.binding.impl;
import java.util.Collections;
import java.util.List;
@@ -23,11 +23,10 @@ import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.opensaml.profile.action.AbstractConditionalProfileAction;
-import org.opensaml.profile.action.ActionSupport;
-import org.opensaml.profile.action.EventIds;
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.handler.AbstractMessageHandler;
+import org.opensaml.messaging.handler.MessageHandlerException;
import org.opensaml.saml.common.messaging.context.SAMLMetadataContext;
import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
import org.opensaml.saml.criterion.RoleDescriptorCriterion;
@@ -37,6 +36,11 @@ import org.opensaml.xmlsec.SignatureSigningParameters;
import org.opensaml.xmlsec.SignatureSigningParametersResolver;
import org.opensaml.xmlsec.context.SecurityParametersContext;
import org.opensaml.xmlsec.criterion.SignatureSigningConfigurationCriterion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
@@ -45,38 +49,28 @@ import net.shibboleth.utilities.java.support.logic.Constraint;
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
import net.shibboleth.utilities.java.support.resolver.ResolverException;
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Function;
-import com.google.common.base.Functions;
-
/**
- * Action that resolves and populates {@link SignatureSigningParameters} on a {@link SecurityParametersContext}
- * created/accessed via a lookup function, by default on the outbound message context.
+ * Handler that resolves and populates {@link SignatureSigningParameters} on a {@link SecurityParametersContext}
+ * created/accessed via a lookup function.
*
- * @event {@link EventIds#PROCEED_EVENT_ID}
- * @event {@link EventIds#INVALID_PROFILE_CTX}
- * @event {@link EventIds#INVALID_SEC_CFG}
*/
-public class PopulateSignatureSigningParameters extends AbstractConditionalProfileAction {
+public class PopulateSignatureSigningParameters extends AbstractMessageHandler {
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(PopulateSignatureSigningParameters.class);
/** Strategy used to look up the {@link SecurityParametersContext} to set the parameters for. */
- @Nonnull private Function<ProfileRequestContext,SecurityParametersContext> securityParametersContextLookupStrategy;
+ @Nonnull private Function<MessageContext,SecurityParametersContext> securityParametersContextLookupStrategy;
/** Strategy used to look up an existing {@link SecurityParametersContext} to copy. */
- @Nullable private Function<ProfileRequestContext,SecurityParametersContext> existingParametersContextLookupStrategy;
+ @Nullable private Function<MessageContext,SecurityParametersContext> existingParametersContextLookupStrategy;
/** Strategy used to look up a per-request {@link SignatureSigningConfiguration} list. */
@NonnullAfterInit
- private Function<ProfileRequestContext,List<SignatureSigningConfiguration>> configurationLookupStrategy;
+ private Function<MessageContext,List<SignatureSigningConfiguration>> configurationLookupStrategy;
/** Strategy used to look up a SAML metadata context. */
- @Nullable private Function<ProfileRequestContext,SAMLMetadataContext> metadataContextLookupStrategy;
+ @Nullable private Function<MessageContext,SAMLMetadataContext> metadataContextLookupStrategy;
/** Resolver for parameters to store into context. */
@NonnullAfterInit private SignatureSigningParametersResolver resolver;
@@ -86,14 +80,12 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
*/
public PopulateSignatureSigningParameters() {
// Create context by default.
- securityParametersContextLookupStrategy = Functions.compose(
- new ChildContextLookup<>(SecurityParametersContext.class, true), new OutboundMessageContextLookup());
+ securityParametersContextLookupStrategy = new ChildContextLookup<>(SecurityParametersContext.class, true);
- // Default: outbound msg context -> SAMLPeerEntityContext -> SAMLMetadataContext
+ // Default: msg context -> SAMLPeerEntityContext -> SAMLMetadataContext
metadataContextLookupStrategy = Functions.compose(
- new ChildContextLookup<>(SAMLMetadataContext.class),
- Functions.compose(new ChildContextLookup<>(SAMLPeerEntityContext.class),
- new OutboundMessageContextLookup()));
+ new ChildContextLookup<SAMLPeerEntityContext,SAMLMetadataContext>(SAMLMetadataContext.class),
+ new ChildContextLookup<MessageContext,SAMLPeerEntityContext>(SAMLPeerEntityContext.class));
}
/**
@@ -102,7 +94,7 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
* @param strategy lookup strategy
*/
public void setSecurityParametersContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,SecurityParametersContext> strategy) {
+ @Nonnull final Function<MessageContext,SecurityParametersContext> strategy) {
ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
securityParametersContextLookupStrategy = Constraint.isNotNull(strategy,
@@ -116,7 +108,7 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
* @param strategy lookup strategy
*/
public void setExistingParametersContextLookupStrategy(
- @Nullable final Function<ProfileRequestContext,SecurityParametersContext> strategy) {
+ @Nullable final Function<MessageContext,SecurityParametersContext> strategy) {
ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
existingParametersContextLookupStrategy = strategy;
@@ -128,7 +120,7 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
* @param strategy lookup strategy
*/
public void setMetadataContextLookupStrategy(
- @Nullable final Function<ProfileRequestContext,SAMLMetadataContext> strategy) {
+ @Nullable final Function<MessageContext,SAMLMetadataContext> strategy) {
ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
metadataContextLookupStrategy = strategy;
@@ -140,7 +132,7 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
* @param strategy lookup strategy
*/
public void setConfigurationLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,List<SignatureSigningConfiguration>> strategy) {
+ @Nonnull final Function<MessageContext,List<SignatureSigningConfiguration>> strategy) {
ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
configurationLookupStrategy = Constraint.isNotNull(strategy,
@@ -167,8 +159,8 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
if (resolver == null) {
throw new ComponentInitializationException("SignatureSigningParametersResolver cannot be null");
} else if (configurationLookupStrategy == null) {
- configurationLookupStrategy = new Function<ProfileRequestContext,List<SignatureSigningConfiguration>>() {
- public List<SignatureSigningConfiguration> apply(final ProfileRequestContext input) {
+ configurationLookupStrategy = new Function<MessageContext,List<SignatureSigningConfiguration>>() {
+ public List<SignatureSigningConfiguration> apply(final MessageContext input) {
return Collections.singletonList(
SecurityConfigurationSupport.getGlobalSignatureSigningConfiguration());
}
@@ -178,9 +170,9 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
/** {@inheritDoc} */
@Override
- protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+ protected boolean doPreInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
- if (super.doPreExecute(profileRequestContext)) {
+ if (super.doPreInvoke(messageContext)) {
log.debug("{} Signing enabled", getLogPrefix());
return true;
} else {
@@ -192,21 +184,20 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
// Checkstyle: CyclomaticComplexity|ReturnCount OFF
/** {@inheritDoc} */
@Override
- protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+ protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {
log.debug("{} Resolving SignatureSigningParameters for request", getLogPrefix());
final SecurityParametersContext paramsCtx =
- securityParametersContextLookupStrategy.apply(profileRequestContext);
+ securityParametersContextLookupStrategy.apply(messageContext);
if (paramsCtx == null) {
log.debug("{} No SecurityParametersContext returned by lookup strategy", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
- return;
+ throw new MessageHandlerException("No SecurityParametersContext returned by lookup strategy");
}
if (existingParametersContextLookupStrategy != null) {
final SecurityParametersContext existingCtx =
- existingParametersContextLookupStrategy.apply(profileRequestContext);
+ existingParametersContextLookupStrategy.apply(messageContext);
if (existingCtx != null && existingCtx.getSignatureSigningParameters() != null) {
log.debug("{} Found existing SecurityParametersContext to copy from", getLogPrefix());
paramsCtx.setSignatureSigningParameters(existingCtx.getSignatureSigningParameters());
@@ -214,17 +205,16 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
}
}
- final List<SignatureSigningConfiguration> configs = configurationLookupStrategy.apply(profileRequestContext);
+ final List<SignatureSigningConfiguration> configs = configurationLookupStrategy.apply(messageContext);
if (configs == null || configs.isEmpty()) {
log.error("{} No SignatureSigningConfiguration returned by lookup strategy", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_SEC_CFG);
- return;
+ throw new MessageHandlerException("No SignatureSigningConfiguration returned by lookup strategy");
}
final CriteriaSet criteria = new CriteriaSet(new SignatureSigningConfigurationCriterion(configs));
if (metadataContextLookupStrategy != null) {
- final SAMLMetadataContext metadataCtx = metadataContextLookupStrategy.apply(profileRequestContext);
+ final SAMLMetadataContext metadataCtx = metadataContextLookupStrategy.apply(messageContext);
if (metadataCtx != null && metadataCtx.getRoleDescriptor() != null) {
log.debug("{} Adding metadata to resolution criteria for signing/digest algorithms", getLogPrefix());
criteria.add(new RoleDescriptorCriterion(metadataCtx.getRoleDescriptor()));
@@ -238,7 +228,7 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
params != null ? "Resolved" : "Failed to resolve");
} catch (final ResolverException e) {
log.error("{} Error resolving SignatureSigningParameters", getLogPrefix(), e);
- ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_SEC_CFG);
+ throw new MessageHandlerException("Error resolving SignatureSigningParameters", e);
}
}
// Checkstyle: CyclomaticComplexity|ReturnCount ON
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/profile/impl/PopulateSignatureSigningParameters.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/profile/impl/PopulateSignatureSigningParameters.java
index 32a9b96..eef132b 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/profile/impl/PopulateSignatureSigningParameters.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/common/profile/impl/PopulateSignatureSigningParameters.java
@@ -23,6 +23,10 @@ import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.RecursiveTypedParentContextLookup;
+import org.opensaml.messaging.handler.MessageHandlerException;
import org.opensaml.profile.action.AbstractConditionalProfileAction;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
@@ -30,35 +34,29 @@ import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
import org.opensaml.saml.common.messaging.context.SAMLMetadataContext;
import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
-import org.opensaml.saml.criterion.RoleDescriptorCriterion;
import org.opensaml.xmlsec.SecurityConfigurationSupport;
import org.opensaml.xmlsec.SignatureSigningConfiguration;
import org.opensaml.xmlsec.SignatureSigningParameters;
import org.opensaml.xmlsec.SignatureSigningParametersResolver;
import org.opensaml.xmlsec.context.SecurityParametersContext;
-import org.opensaml.xmlsec.criterion.SignatureSigningConfigurationCriterion;
-
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
-import net.shibboleth.utilities.java.support.resolver.ResolverException;
-
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
import com.google.common.base.Functions;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
/**
* Action that resolves and populates {@link SignatureSigningParameters} on a {@link SecurityParametersContext}
* created/accessed via a lookup function, by default on the outbound message context.
*
* @event {@link EventIds#PROCEED_EVENT_ID}
- * @event {@link EventIds#INVALID_PROFILE_CTX}
- * @event {@link EventIds#INVALID_SEC_CFG}
+ * @event {@link EventIds#INVALID_MSG_CTX}
+ * @event {@link EventIds#MESSAGE_PROC_ERROR}
*/
public class PopulateSignatureSigningParameters extends AbstractConditionalProfileAction {
@@ -81,6 +79,9 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
/** Resolver for parameters to store into context. */
@NonnullAfterInit private SignatureSigningParametersResolver resolver;
+ /** MessageHandler delegate. */
+ @NonnullAfterInit private org.opensaml.saml.common.binding.impl.PopulateSignatureSigningParameters delegate;
+
/**
* Constructor.
*/
@@ -160,6 +161,17 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
}
/** {@inheritDoc} */
+ protected boolean doPreExecute(final ProfileRequestContext profileRequestContext) {
+ if (super.doPreExecute(profileRequestContext)) {
+ log.debug("{} Signing enabled", getLogPrefix());
+ return true;
+ } else {
+ log.debug("{} Signing not enabled", getLogPrefix());
+ return false;
+ }
+ }
+
+ /** {@inheritDoc} */
@Override
protected void doInitialize() throws ComponentInitializationException {
super.doInitialize();
@@ -174,73 +186,51 @@ public class PopulateSignatureSigningParameters extends AbstractConditionalProfi
}
};
}
- }
-
- /** {@inheritDoc} */
- @Override
- protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
- if (super.doPreExecute(profileRequestContext)) {
- log.debug("{} Signing enabled", getLogPrefix());
- return true;
- } else {
- log.debug("{} Signing not enabled", getLogPrefix());
- return false;
- }
- }
-
-// Checkstyle: CyclomaticComplexity|ReturnCount OFF
- /** {@inheritDoc} */
- @Override
- protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
-
- log.debug("{} Resolving SignatureSigningParameters for request", getLogPrefix());
+ final Function<MessageContext, ProfileRequestContext> prcLookup =
+ new RecursiveTypedParentContextLookup<>(ProfileRequestContext.class);
- final SecurityParametersContext paramsCtx =
- securityParametersContextLookupStrategy.apply(profileRequestContext);
- if (paramsCtx == null) {
- log.debug("{} No SecurityParametersContext returned by lookup strategy", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
- return;
- }
+ delegate = new org.opensaml.saml.common.binding.impl.PopulateSignatureSigningParameters();
+
+ delegate.setSignatureSigningParametersResolver(resolver);
+ delegate.setConfigurationLookupStrategy(Functions.compose(configurationLookupStrategy, prcLookup));
+ delegate.setSecurityParametersContextLookupStrategy(
+ Functions.compose(securityParametersContextLookupStrategy, prcLookup));
if (existingParametersContextLookupStrategy != null) {
- final SecurityParametersContext existingCtx =
- existingParametersContextLookupStrategy.apply(profileRequestContext);
- if (existingCtx != null && existingCtx.getSignatureSigningParameters() != null) {
- log.debug("{} Found existing SecurityParametersContext to copy from", getLogPrefix());
- paramsCtx.setSignatureSigningParameters(existingCtx.getSignatureSigningParameters());
- return;
- }
+ delegate.setExistingParametersContextLookupStrategy(
+ Functions.compose(existingParametersContextLookupStrategy, prcLookup));
}
- final List<SignatureSigningConfiguration> configs = configurationLookupStrategy.apply(profileRequestContext);
- if (configs == null || configs.isEmpty()) {
- log.error("{} No SignatureSigningConfiguration returned by lookup strategy", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_SEC_CFG);
- return;
+ if (metadataContextLookupStrategy != null) {
+ delegate.setMetadataContextLookupStrategy(Functions.compose(metadataContextLookupStrategy, prcLookup));
}
- final CriteriaSet criteria = new CriteriaSet(new SignatureSigningConfigurationCriterion(configs));
-
- if (metadataContextLookupStrategy != null) {
- final SAMLMetadataContext metadataCtx = metadataContextLookupStrategy.apply(profileRequestContext);
- if (metadataCtx != null && metadataCtx.getRoleDescriptor() != null) {
- log.debug("{} Adding metadata to resolution criteria for signing/digest algorithms", getLogPrefix());
- criteria.add(new RoleDescriptorCriterion(metadataCtx.getRoleDescriptor()));
- }
+ delegate.initialize();
+ }
+
+ /** {@inheritDoc} */
+ protected void doDestroy() {
+ super.doDestroy();
+ if (delegate != null) {
+ delegate.destroy();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
+ if (profileRequestContext.getOutboundMessageContext() == null) {
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
+ return;
}
try {
- final SignatureSigningParameters params = resolver.resolveSingle(criteria);
- paramsCtx.setSignatureSigningParameters(params);
- log.debug("{} {} SignatureSigningParameters", getLogPrefix(),
- params != null ? "Resolved" : "Failed to resolve");
- } catch (final ResolverException e) {
- log.error("{} Error resolving SignatureSigningParameters", getLogPrefix(), e);
- ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_SEC_CFG);
+ delegate.invoke(profileRequestContext.getOutboundMessageContext());
+ ActionSupport.buildProceedEvent(profileRequestContext);
+ } catch (final MessageHandlerException e) {
+ ActionSupport.buildEvent(profileRequestContext, EventIds.MESSAGE_PROC_ERROR);
}
}
-// Checkstyle: CyclomaticComplexity|ReturnCount ON
}
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/common/profile/impl/PopulateSignatureSigningParametersTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/common/profile/impl/PopulateSignatureSigningParametersTest.java
index 8a566bb..79f8ab1 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/common/profile/impl/PopulateSignatureSigningParametersTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/common/profile/impl/PopulateSignatureSigningParametersTest.java
@@ -65,7 +65,7 @@ public class PopulateSignatureSigningParametersTest extends OpenSAMLInitBaseTest
prc.setOutboundMessageContext(null);
action.execute(prc);
- ActionTestingSupport.assertEvent(prc, EventIds.INVALID_PROFILE_CTX);
+ ActionTestingSupport.assertEvent(prc, EventIds.INVALID_MSG_CTX);
}
@Test public void testResolverError() throws Exception {
@@ -73,7 +73,7 @@ public class PopulateSignatureSigningParametersTest extends OpenSAMLInitBaseTest
action.initialize();
action.execute(prc);
- ActionTestingSupport.assertEvent(prc, EventIds.INVALID_SEC_CFG);
+ ActionTestingSupport.assertEvent(prc, EventIds.MESSAGE_PROC_ERROR);
}
@Test public void testSuccess() throws Exception {
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list