/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.sshd.common.util.security; import java.lang.reflect.Method; import java.security.GeneralSecurityException; import java.security.Provider; import java.util.Objects; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ValidateUtils; /** * @param <T> Type of security entity being generated by this factory * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a> */ public interface SecurityEntityFactory<T> { Class<T> getEntityType(); T getInstance(String algorithm) throws GeneralSecurityException; /** * Uses reflection in order to wrap the {@code getInstance} method(s) * as a security entity factory. * * @param <F> Type of entity being generated by the factor * @param entityType The entity type class * @param registrar The {@code SecurityProviderRegistrar} to use - if * {@code null} then default provider is used (if specified). * @param defaultProvider Default provider choice to use if no registrar * provided. If {@code null}/empty then JCE default is used * @return The {@link SecurityEntityFactory} for the entity * @throws ReflectiveOperationException If failed to create the factory * @see #toDefaultFactory(Class) * @see #toNamedProviderFactory(Class, String) * @see #toProviderInstanceFactory(Class, Provider) * @see SecurityProviderChoice#isNamedProviderUsed() * @see SecurityProviderChoice#getSecurityProvider() */ static <F> SecurityEntityFactory<F> toFactory( Class<F> entityType, SecurityProviderChoice registrar, SecurityProviderChoice defaultProvider) throws ReflectiveOperationException { if (registrar == null) { if ((defaultProvider == null) || (defaultProvider == SecurityProviderChoice.EMPTY)) { return toDefaultFactory(entityType); } else if (defaultProvider.isNamedProviderUsed()) { return toNamedProviderFactory(entityType, defaultProvider.getName()); } else { return toProviderInstanceFactory(entityType, defaultProvider.getSecurityProvider()); } } else if (registrar.isNamedProviderUsed()) { return toNamedProviderFactory(entityType, registrar.getName()); } else { return toProviderInstanceFactory(entityType, registrar.getSecurityProvider()); } } static <F> SecurityEntityFactory<F> toDefaultFactory(Class<F> entityType) throws ReflectiveOperationException { Method m = entityType.getDeclaredMethod("getInstance", String.class); return new SecurityEntityFactory<F>() { private final String s = SecurityEntityFactory.class.getSimpleName() + "[" + entityType.getSimpleName() + "]" + "[default]"; @Override public Class<F> getEntityType() { return entityType; } @Override public F getInstance(String algorithm) throws GeneralSecurityException { try { Object value = m.invoke(null, algorithm); return entityType.cast(value); } catch (ReflectiveOperationException t) { Throwable e = GenericUtils.peelException(t); if (e instanceof GeneralSecurityException) { throw (GeneralSecurityException) e; } else if (e instanceof RuntimeException) { throw (RuntimeException) e; } else if (e instanceof Error) { throw (Error) e; } else { throw new GeneralSecurityException(e); } } } @Override public String toString() { return s; } }; } static <F> SecurityEntityFactory<F> toNamedProviderFactory(Class<F> entityType, String name) throws ReflectiveOperationException { ValidateUtils.checkNotNullAndNotEmpty(name, "No provider name specified"); Method m = entityType.getDeclaredMethod("getInstance", String.class, String.class); return new SecurityEntityFactory<F>() { private final String s = SecurityEntityFactory.class.getSimpleName() + "[" + entityType.getSimpleName() + "]" + "[" + name + "]"; @Override public Class<F> getEntityType() { return entityType; } @Override public F getInstance(String algorithm) throws GeneralSecurityException { try { Object value = m.invoke(null, algorithm, name); return entityType.cast(value); } catch (ReflectiveOperationException t) { Throwable e = GenericUtils.peelException(t); if (e instanceof GeneralSecurityException) { throw (GeneralSecurityException) e; } else if (e instanceof RuntimeException) { throw (RuntimeException) e; } else if (e instanceof Error) { throw (Error) e; } else { throw new GeneralSecurityException(e); } } } @Override public String toString() { return s; } }; } static <F> SecurityEntityFactory<F> toProviderInstanceFactory(Class<F> entityType, Provider provider) throws ReflectiveOperationException { Objects.requireNonNull(provider, "No provider instance"); Method m = entityType.getDeclaredMethod("getInstance", String.class, Provider.class); return new SecurityEntityFactory<F>() { private final String s = SecurityEntityFactory.class.getSimpleName() + "[" + entityType.getSimpleName() + "]" + "[" + Provider.class.getSimpleName() + "]" + "[" + provider.getName() + "]"; @Override public Class<F> getEntityType() { return entityType; } @Override public F getInstance(String algorithm) throws GeneralSecurityException { try { Object value = m.invoke(null, algorithm, provider); return entityType.cast(value); } catch (ReflectiveOperationException t) { Throwable e = GenericUtils.peelException(t); if (e instanceof GeneralSecurityException) { throw (GeneralSecurityException) e; } else if (e instanceof RuntimeException) { throw (RuntimeException) e; } else if (e instanceof Error) { throw (Error) e; } else { throw new GeneralSecurityException(e); } } } @Override public String toString() { return s; } }; } }