Skip to content

Commit

Permalink
Make password secret and do not store in config file
Browse files Browse the repository at this point in the history
  • Loading branch information
minborg committed Jun 8, 2015
1 parent 22d9a53 commit 4d4014c
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 48 deletions.
2 changes: 1 addition & 1 deletion src/main/java/com/speedment/core/Test.java
Expand Up @@ -95,7 +95,7 @@ public static void main(String[] args) {


handler.schemasPopulated().forEachOrdered(schema -> { handler.schemasPopulated().forEachOrdered(schema -> {


Function<Node, Stream<Node>> traverser = n -> n.asParent().map(p -> p.stream()).orElse(Stream.empty()).map(c -> (Node) c); final Function<Node, Stream<Node>> traverser = n -> n.asParent().map(p -> p.stream()).orElse(Stream.empty()).map(c -> (Node) c);


Trees.traverse(schema, Trees.traverse(schema,
traverser, traverser,
Expand Down
29 changes: 14 additions & 15 deletions src/main/java/com/speedment/core/config/model/aspects/Node.java
Expand Up @@ -28,17 +28,16 @@
* *
* @author Emil Forslund * @author Emil Forslund
*/ */

public interface Node extends Nameable, Enableable { public interface Node extends Nameable, Enableable {

@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
default <P extends Parent<?>> Optional<P> getParent(Class<P> parentClass) { default <P extends Parent<?>> Optional<P> getParent(Class<P> parentClass) {
return Optional.of(this) return Optional.of(this)
.filter(e -> e.isChildInterface()) .filter(e -> e.isChildInterface())
.map(e -> (Child<?>) e) .map(e -> (Child<?>) e)
.flatMap(e -> e.getParent()) .flatMap(e -> e.getParent())
.filter(e -> parentClass.isAssignableFrom(e.getClass())) .filter(e -> parentClass.isAssignableFrom(e.getClass()))
.map(e -> (P) e); .map(e -> (P) e);
} }


default boolean isParentInterface() { default boolean isParentInterface() {
Expand All @@ -63,19 +62,19 @@ default Optional<? extends Parent<?>> asParent() {


@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
default Stream<? extends Parent<?>> ancestors() { default Stream<? extends Parent<?>> ancestors() {
return Trees.walkOptional( return getParent(Parent.class).map(parent -> Trees.walkOptional(
getParent(Parent.class).get(), parent,
(Parent<?> p) -> p.getParent(Parent.class).map(p2 -> (Parent<?>) p2), (Parent<?> p) -> p.getParent(Parent.class).map(p2 -> (Parent<?>) p2),
Trees.WalkingOrder.BACKWARD Trees.WalkingOrder.BACKWARD
); )).orElse(Stream.empty());
} }


@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
default <E extends Node> Optional<E> ancestor(final Class<E> clazz) { default <E extends Node> Optional<E> ancestor(final Class<E> clazz) {
return ancestors() return ancestors()
.filter(p -> clazz.isAssignableFrom(p.getClass())) .filter(p -> clazz.isAssignableFrom(p.getClass()))
.map(p -> (E) p) .map(p -> (E) p)
.findFirst(); .findFirst();
} }


default String getRelativeName(final Class<? extends Parent<?>> from) { default String getRelativeName(final Class<? extends Parent<?>> from) {
Expand Down
Expand Up @@ -20,7 +20,6 @@
import com.speedment.core.config.model.aspects.Node; import com.speedment.core.config.model.aspects.Node;
import static com.speedment.util.Beans.getterBeanPropertyNameAndValue; import static com.speedment.util.Beans.getterBeanPropertyNameAndValue;
import com.speedment.util.java.JavaLanguage; import com.speedment.util.java.JavaLanguage;
import com.speedment.util.stream.CollectorUtil;
import groovy.lang.Binding; import groovy.lang.Binding;
import groovy.lang.GroovyShell; import groovy.lang.GroovyShell;
import groovy.util.DelegatingScript; import groovy.util.DelegatingScript;
Expand All @@ -42,44 +41,22 @@
public class GroovyParser { public class GroovyParser {


private static final Package IMPORT_PACKAGE = com.speedment.core.config.model.parameters.FieldStorageType.class.getPackage(); private static final Package IMPORT_PACKAGE = com.speedment.core.config.model.parameters.FieldStorageType.class.getPackage();
private static final String NL = "\n";


public static String toGroovy(final Node node) { public static String toGroovy(final Node node) {
// return IMPORT_PACKAGE.getName() + ".*" + NL + NL + toGroovy(node, 0);
// //return "import com.speedment.orm.config.model.parameters.*" + NL + NL + toGroovy(node, 0);
return toGroovyLines(node).collect(joining("\n")); return toGroovyLines(node).collect(joining("\n"));
} }


public static Stream<String> toGroovyLines(final Node node) { public static Stream<String> toGroovyLines(final Node node) {
final Stream.Builder<String> sb = Stream.builder(); final Stream.Builder<String> sb = Stream.builder();
sb.add("import " + IMPORT_PACKAGE.getName() + ".*"); sb.add("import " + IMPORT_PACKAGE.getName() + ".*");
//sb.add("import com.speedment.orm.config.model.parameters.*");
sb.add(""); sb.add("");
toGroovyLines(sb, node, 0); toGroovyLines(sb, node, 0);
return sb.build(); return sb.build();
} }


// private static String toGroovy(final Node node, final int indentLevel) {
// return CollectorUtil.of(StringBuilder::new, sb -> {
// MethodsParser.streamOfExternal(node.getClass())
// .sorted((m0, m1) -> m0.getName().compareTo(m1.getName()))
// .forEach(m -> getterBeanPropertyNameAndValue(m, node)
// .ifPresent(t -> indent(sb, indentLevel).append(t).append(NL))
// );
//
// Optional.of(node).flatMap(n -> n.asParent()).ifPresent(n
// -> n.stream().forEach(c -> {
// indent(sb, indentLevel).append(JavaLanguage.javaVariableName(c.getInterfaceMainClass().getSimpleName())).append(" {").append(NL);
// sb.append(toGroovy(c, indentLevel + 1));
// indent(sb, indentLevel).append("}").append(NL);
// })
// );
// }, StringBuilder::toString);
// }

private static Stream.Builder<String> toGroovyLines(final Stream.Builder<String> sb, final Node node, final int indentLevel) { private static Stream.Builder<String> toGroovyLines(final Stream.Builder<String> sb, final Node node, final int indentLevel) {


MethodsParser.streamOfExternal(node.getClass()) MethodsParser.streamOfExternalNoneSecretGetters(node.getClass())
.sorted((m0, m1) -> m0.getName().compareTo(m1.getName())) .sorted((m0, m1) -> m0.getName().compareTo(m1.getName()))
.forEach(m -> getterBeanPropertyNameAndValue(m, node) .forEach(m -> getterBeanPropertyNameAndValue(m, node)
.ifPresent(t -> sb.add(indent(indentLevel) + t)) .ifPresent(t -> sb.add(indent(indentLevel) + t))
Expand Down
Expand Up @@ -39,13 +39,24 @@ private MethodsParser() {}
public static final Predicate<Method> public static final Predicate<Method>
METHOD_IS_PUBLIC = (m) -> Modifier.isPublic(m.getModifiers()), METHOD_IS_PUBLIC = (m) -> Modifier.isPublic(m.getModifiers()),
METHOD_IS_GETTER = (m) -> m.getParameterCount() == 0 && (m.getName().startsWith("get") || m.getName().startsWith("is")), METHOD_IS_GETTER = (m) -> m.getParameterCount() == 0 && (m.getName().startsWith("get") || m.getName().startsWith("is")),
METHOD_IS_SETTER = (m) -> m.getParameterCount() == 1 && (m.getName().startsWith("set")),
METHOD_IS_EXTERNAL = MethodsParser::isExternal, METHOD_IS_EXTERNAL = MethodsParser::isExternal,
METHOD_IS_EXTERNAL_AND_NONE_SECRET = MethodsParser::isExternalAndNoneSecret,
METHOD_IS_EXTERNAL_AND_SECRET = MethodsParser::isExternalAndSecret,
METHOD_IS_VISIBLE_IN_GUI = MethodsParser::isVisibleInGUI; METHOD_IS_VISIBLE_IN_GUI = MethodsParser::isVisibleInGUI;


public static Stream<Method> streamOfExternal(Class<?> clazz) { public static Stream<Method> streamOfExternalNoneSecretGetters(Class<?> clazz) {
return getMethods(clazz, return getMethods(clazz,
METHOD_IS_PUBLIC METHOD_IS_PUBLIC
.and(METHOD_IS_GETTER) .and(METHOD_IS_GETTER)
.and(METHOD_IS_EXTERNAL_AND_NONE_SECRET)
).stream();
}

public static Stream<Method> streamOfExternalSetters(Class<?> clazz) {
return getMethods(clazz,
METHOD_IS_PUBLIC
.and(METHOD_IS_SETTER)
.and(METHOD_IS_EXTERNAL) .and(METHOD_IS_EXTERNAL)
).stream(); ).stream();
} }
Expand Down Expand Up @@ -98,6 +109,26 @@ private static boolean isVisibleInGUI(final Method method, final Class<?> clazz)
.isPresent(); .isPresent();
} }


private static boolean isExternalAndNoneSecret(Method method) {
return isExternalAndNoneSecret(method, method.getDeclaringClass());
}

private static boolean isExternalAndNoneSecret(final Method method, final Class<?> clazz) {
return Optional.ofNullable(getExternalFor(method, clazz))
.filter(e-> !e.isSecret())
.isPresent();
}

private static boolean isExternalAndSecret(Method method) {
return isExternalAndSecret(method, method.getDeclaringClass());
}

private static boolean isExternalAndSecret(final Method method, final Class<?> clazz) {
return Optional.ofNullable(getExternalFor(method, clazz))
.filter(External::isSecret)
.isPresent();
}

private static Set<Method> addMethods(Set<Method> methods, Class<?> clazz, Predicate<Method> filter) { private static Set<Method> addMethods(Set<Method> methods, Class<?> clazz, Predicate<Method> filter) {
if (clazz == Object.class) { if (clazz == Object.class) {
return methods; return methods;
Expand Down
Expand Up @@ -16,21 +16,32 @@
*/ */
package com.speedment.core.runtime; package com.speedment.core.runtime;


import com.speedment.core.config.model.External;
import com.speedment.core.config.model.Project; import com.speedment.core.config.model.Project;
import com.speedment.core.config.model.aspects.Node;
import com.speedment.core.config.model.impl.utils.GroovyParser; import com.speedment.core.config.model.impl.utils.GroovyParser;
import com.speedment.core.config.model.impl.utils.MethodsParser;
import com.speedment.core.core.Buildable; import com.speedment.core.core.Buildable;
import com.speedment.core.lifecycle.AbstractLifecycle; import com.speedment.core.lifecycle.AbstractLifecycle;
import com.speedment.core.manager.Manager; import com.speedment.core.manager.Manager;
import com.speedment.core.exception.SpeedmentException; import com.speedment.core.exception.SpeedmentException;
import com.speedment.core.platform.Platform; import com.speedment.core.platform.Platform;
import com.speedment.core.platform.component.ManagerComponent; import com.speedment.core.platform.component.ManagerComponent;
import com.speedment.core.platform.component.ProjectComponent; import com.speedment.core.platform.component.ProjectComponent;
import com.speedment.core.runtime.typemapping.StandardJavaTypeMapping;
import static com.speedment.util.Beans.beanPropertyName;
import com.speedment.util.Trees;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import java.util.stream.Stream;


/** /**
* *
Expand All @@ -39,12 +50,43 @@
*/ */
public abstract class SpeedmentApplicationLifecycle<T extends SpeedmentApplicationLifecycle<T>> extends AbstractLifecycle<T> { public abstract class SpeedmentApplicationLifecycle<T extends SpeedmentApplicationLifecycle<T>> extends AbstractLifecycle<T> {


private String dbmsPassword;
private final Map<String, String> dbmsPasswords;
private ApplicationMetadata speedmentApplicationMetadata; private ApplicationMetadata speedmentApplicationMetadata;
private Path configPath; private Path configPath;


public SpeedmentApplicationLifecycle() { public SpeedmentApplicationLifecycle() {
super(); super();
configPath = null; configPath = null;
dbmsPasswords = new ConcurrentHashMap<>();
}

/**
* Configures a password for all dbmses in this project. The password will
* then be applied after the configuration has been read and after the
* System properties has been applied but before
* configureDbmsPassword(dbmsName, password) is called.
*
* @param password the password to use for all dbms:es in this project.
* @return this instance
*/
public T configureDbmsPassword(final String password) {
dbmsPassword = password;
return self();
}

/**
* Configures a password for the named dbms. The password will then be
* applied after the configuration has been read and after the System
* properties has been applied.
*
* @param dbmsName the name of the dbms
* @param password the password to use for the named dbms.
* @return this instance
*/
public T configureDbmsPassword(final String dbmsName, final String password) {
dbmsPasswords.put(dbmsName, password);
return self();
} }


@Override @Override
Expand All @@ -70,14 +112,47 @@ protected void onStop() {
protected void loadAndSetProject() { protected void loadAndSetProject() {
try { try {
final Optional<Path> oPath = getConfigPath(); final Optional<Path> oPath = getConfigPath();
final Project project;
if (oPath.isPresent()) { if (oPath.isPresent()) {
final Project p = GroovyParser.projectFromGroovy(oPath.get()); project = GroovyParser.projectFromGroovy(oPath.get());
Platform.get().get(ProjectComponent.class).setProject(p);
} else { } else {
final Project p = GroovyParser.projectFromGroovy(getSpeedmentApplicationMetadata().getMetadata()); project = GroovyParser.projectFromGroovy(getSpeedmentApplicationMetadata().getMetadata());
Platform.get().get(ProjectComponent.class).setProject(p);
} }


// Apply overridden values from the system properties (if any)
final Function<Node, Stream<Node>> traverser = n -> n.asParent().map(p -> p.stream()).orElse(Stream.empty()).map(c -> (Node) c);
Trees.traverse(project, traverser, Trees.TraversalOrder.DEPTH_FIRST_PRE)
.forEach((Node node) -> {
final Class<?> clazz = node.getClass();
MethodsParser.streamOfExternalSetters(clazz).forEach(
method -> {
final String path = "speedment.project." + node.getRelativeName(Project.class) + "." + beanPropertyName(method);
Optional.ofNullable(System.getProperty(path)).ifPresent(propString -> {
final External external = MethodsParser.getExternalFor(method, clazz);
final Class<?> targetJavaType = external.type();
final Object val = StandardJavaTypeMapping.parse(targetJavaType, propString);
try {
method.invoke(node, val);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new SpeedmentException("Unable to invoke " + method + " for " + node + " with argument " + val + " (" + propString + ")");
}
});
}
);
});

// Apply overidden passwords (if any) for all dbms:es
Optional.ofNullable(dbmsPassword).ifPresent(pwd -> {
project.stream().forEach(dbms -> dbms.setPassword(pwd));
});

// Apply overidden passwords (if any) for any named dbms
project.stream().forEach(dbms -> {
Optional.ofNullable(dbmsPasswords.get(dbms.getName())).ifPresent(pwd -> dbms.setPassword(pwd));
});

Platform.get().get(ProjectComponent.class).setProject(project);

} catch (IOException ioe) { } catch (IOException ioe) {
throw new SpeedmentException("Failed to read config file", ioe); throw new SpeedmentException("Failed to read config file", ioe);
} }
Expand Down
Expand Up @@ -27,5 +27,5 @@ public interface JavaTypeMapping {
Class<?> getJavaClass(); Class<?> getJavaClass();


String getResultSetMethodName(Dbms dbms); String getResultSetMethodName(Dbms dbms);

} }
Expand Up @@ -17,6 +17,7 @@
package com.speedment.core.runtime.typemapping; package com.speedment.core.runtime.typemapping;


import com.speedment.core.config.model.Dbms; import com.speedment.core.config.model.Dbms;
import com.speedment.core.exception.SpeedmentException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
Expand All @@ -43,6 +44,7 @@ public enum StandardJavaTypeMapping implements JavaTypeMapping {


// If you add a mapping X here, make sure that AbstractSqlManager has a // If you add a mapping X here, make sure that AbstractSqlManager has a
// corresponding method getX(ResultSet, String) // corresponding method getX(ResultSet, String)

OBJECT(Object.class, "Object", s -> (Object) s), OBJECT(Object.class, "Object", s -> (Object) s),
BOOLEAN(Boolean.class, "Boolean", Boolean::parseBoolean), BOOLEAN(Boolean.class, "Boolean", Boolean::parseBoolean),
BYTE(Byte.class, "Byte", Byte::parseByte), BYTE(Byte.class, "Byte", Byte::parseByte),
Expand All @@ -64,7 +66,7 @@ public enum StandardJavaTypeMapping implements JavaTypeMapping {
try { try {
return new URL(s); return new URL(s);
} catch (MalformedURLException mfe) { } catch (MalformedURLException mfe) {
throw new RuntimeException(mfe); throw new SpeedmentException(mfe);
} }
}), }),
ROW_ID(RowId.class, "RowId", s -> unableToMap(RowId.class)), ROW_ID(RowId.class, "RowId", s -> unableToMap(RowId.class)),
Expand Down
Expand Up @@ -56,7 +56,7 @@ public TablePropertyManager(TreeView<Child<?>> view) {
public Stream<TableProperty<?>> propertiesFor(List<Child<?>> nodes) { public Stream<TableProperty<?>> propertiesFor(List<Child<?>> nodes) {


return nodes.stream().flatMap(node -> { return nodes.stream().flatMap(node -> {
return MethodsParser.streamOfExternal(node.getClass()) return MethodsParser.streamOfExternalNoneSecretGetters(node.getClass())
.filter(METHOD_IS_VISIBLE_IN_GUI) .filter(METHOD_IS_VISIBLE_IN_GUI)
.sorted((m0, m1) -> m0.getName().compareTo(m1.getName())) .sorted((m0, m1) -> m0.getName().compareTo(m1.getName()))
//.sorted(comparing(Method::getName)) //.sorted(comparing(Method::getName))
Expand Down

0 comments on commit 4d4014c

Please sign in to comment.