You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by si...@apache.org on 2009/11/20 09:06:24 UTC

svn commit: r882441 - in /labs/magma/trunk/lateconfig-impl: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/magma/ src/main/java/org/apache/magma/lateconfig/ src/main/resources/ src/test/ src/test/...

Author: simoneg
Date: Fri Nov 20 08:06:23 2009
New Revision: 882441

URL: http://svn.apache.org/viewvc?rev=882441&view=rev
Log:
LABS-365 : implementation for contextualized external configuration

Added:
    labs/magma/trunk/lateconfig-impl/pom.xml
    labs/magma/trunk/lateconfig-impl/src/
    labs/magma/trunk/lateconfig-impl/src/main/
    labs/magma/trunk/lateconfig-impl/src/main/java/
    labs/magma/trunk/lateconfig-impl/src/main/java/org/
    labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/
    labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/
    labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/lateconfig/
    labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/lateconfig/LateConfigurationHook.aj
    labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/lateconfig/LateConfigurator.java
    labs/magma/trunk/lateconfig-impl/src/main/resources/
    labs/magma/trunk/lateconfig-impl/src/test/
    labs/magma/trunk/lateconfig-impl/src/test/java/
    labs/magma/trunk/lateconfig-impl/src/test/java/org/
    labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/
    labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/
    labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/
    labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/LateConfigBean.java
    labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/LateConfigTest.java
    labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/OtherTriggerBean.java
    labs/magma/trunk/lateconfig-impl/src/test/resources/
    labs/magma/trunk/lateconfig-impl/src/test/resources/META-INF/
    labs/magma/trunk/lateconfig-impl/src/test/resources/META-INF/lateconfig.properties

Added: labs/magma/trunk/lateconfig-impl/pom.xml
URL: http://svn.apache.org/viewvc/labs/magma/trunk/lateconfig-impl/pom.xml?rev=882441&view=auto
==============================================================================
--- labs/magma/trunk/lateconfig-impl/pom.xml (added)
+++ labs/magma/trunk/lateconfig-impl/pom.xml Fri Nov 20 08:06:23 2009
@@ -0,0 +1,37 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>magma-parent</artifactId>
+    <groupId>org.apache.magma</groupId>
+    <version>3</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.magma</groupId>
+  <artifactId>lateconfig-impl</artifactId>
+  <packaging>magma</packaging>
+  <name>Magma Late Configuration Implementation</name>
+  <version>0.0.3-SNAPSHOT</version>
+  <description>	</description>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.magma</groupId>
+      <artifactId>lateconfig-api</artifactId>
+      <version>0.0.3-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.magma</groupId>
+      <artifactId>foundation-beans</artifactId>
+      <version>0.0.3-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.magma</groupId>
+      <artifactId>foundation-basics</artifactId>
+      <version>0.0.3-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+    	<groupId>junit</groupId>
+    	<artifactId>junit</artifactId>
+    	<version>4.7</version>
+    	<scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file

Added: labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/lateconfig/LateConfigurationHook.aj
URL: http://svn.apache.org/viewvc/labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/lateconfig/LateConfigurationHook.aj?rev=882441&view=auto
==============================================================================
--- labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/lateconfig/LateConfigurationHook.aj (added)
+++ labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/lateconfig/LateConfigurationHook.aj Fri Nov 20 08:06:23 2009
@@ -0,0 +1,49 @@
+package org.apache.magma.lateconfig;
+
+import java.util.List;
+
+import org.apache.magma.basics.MagmaException;
+import org.aspectj.lang.reflect.MethodSignature;
+
+
+public aspect LateConfigurationHook {
+
+	public interface LateConfigurationSupport { }
+	
+	declare parents: (@LateConfigurable *) implements LateConfigurationSupport;
+		
+	public pointcut methodConfigurationTrigger() : 
+		execution(@LateConfigurationTrigger public * LateConfigurationSupport+.*(..));
+	public pointcut constructorConfigurationTrigger() :
+		execution(@LateConfigurationTrigger LateConfigurationSupport+.new(..));
+	
+	public pointcut configurableMethod() : execution(@LateConfigurable public * LateConfigurationSupport+.*(..));
+		
+	private List<String> LateConfigurationSupport.configured = null;
+	private boolean LateConfigurationSupport.configuring = false;
+
+	after(LateConfigurationSupport bean) : constructorConfigurationTrigger() && this(bean) {
+		if (bean.configured != null || bean.configuring) return;
+		bean.configuring = true;
+		bean.configured = LateConfigurator.lateConfigure(bean);
+	}
+	
+	before(LateConfigurationSupport bean) : methodConfigurationTrigger() && this(bean) {
+		if (bean.configured != null || bean.configuring) return;
+		bean.configuring = true;
+		bean.configured = LateConfigurator.lateConfigure(bean);
+	}
+	
+	Object around(LateConfigurationSupport bean) : configurableMethod() && this(bean) {
+		if (bean.configured == null) return proceed(bean);
+		MethodSignature signature = (MethodSignature)thisJoinPoint.getSignature();
+		String methodname = signature.getName();
+		if (!bean.configured.contains(methodname)) return proceed(bean);
+		Class rt = signature.getReturnType();
+		if (rt.equals(Void.TYPE)) return null;
+		if (rt.isAssignableFrom(bean.getClass())) return bean;
+		throw new MagmaException("Don't know what to return after late configuration for method {0}, only void or same bean type are supported, not {1}", signature.toLongString(), rt);
+	}
+	
+	
+}

Added: labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/lateconfig/LateConfigurator.java
URL: http://svn.apache.org/viewvc/labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/lateconfig/LateConfigurator.java?rev=882441&view=auto
==============================================================================
--- labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/lateconfig/LateConfigurator.java (added)
+++ labs/magma/trunk/lateconfig-impl/src/main/java/org/apache/magma/lateconfig/LateConfigurator.java Fri Nov 20 08:06:23 2009
@@ -0,0 +1,172 @@
+package org.apache.magma.lateconfig;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
+
+import org.apache.magma.basics.MagmaException;
+import org.apache.magma.basics.context.RunningContext;
+import org.apache.magma.basics.startup.CycleThreadLocal;
+import org.apache.magma.conversion.Converter;
+import org.apache.magma.conversion.Converters;
+import org.apache.magma.lateconfig.LateConfigurationHook.LateConfigurationSupport;
+import org.apache.magma.settings.ContextSettingsHolder;
+import org.apache.magma.settings.Settings;
+
+public class LateConfigurator {
+
+	protected static ContextSettingsHolder prodholder = new ContextSettingsHolder();
+	protected static CycleThreadLocal<ContextSettingsHolder> devholder = new CycleThreadLocal<ContextSettingsHolder>();
+	
+	public static List<String> lateConfigure(LateConfigurationSupport bean) {
+		ContextSettingsHolder holder = initSettings();
+		RunningContext.get().push(bean.getClass());
+		String[] prop = null;
+		try {
+			List<String> ret = new ArrayList<String>();
+			Class<? extends LateConfigurationSupport> clazz = bean.getClass();
+			// TODO cache configurable methods
+			Method[] methods = clazz.getMethods();
+			for (Method method : methods) {
+				if (method.isAnnotationPresent(LateConfigurable.class)) {
+					String keyname = method.getName();
+					if (keyname.startsWith("set")) {
+						keyname = keyname.substring(3);
+					}
+					prop = null;
+					prop = holder.getEntry(keyname);
+					if (prop == null) continue;
+					// TODO cache this conversion
+					Class<?>[] types = method.getParameterTypes();
+					Object[] params = new Object[types.length];
+					if (types.length > 0) {
+						// Special case of a single string
+						if (types.length == 1 && types[0].equals(String.class)) {
+							params[0] = prop[prop.length - 1];
+						} else {
+							String val = prop[prop.length - 1];
+							String[] strparams = parseArguments(val, prop);
+							// TODO how to handle overridden methods?
+							if (strparams.length != types.length) throw new MagmaException("Wrong number of parameters for late config of {0},{1}, expected {2} but found {3} in {4}", bean.getClass(), method.getName(), types.length, strparams.length, Arrays.toString(prop));
+							for (int i = 0; i < types.length; i++) {
+								Converter<?> converter = Converters.getConverterFor(types[i]);
+								if (converter == null) {
+									throw new MagmaException("Cannot find a converter for {0}, needed for late configuration of {1}", types[i], Arrays.toString(prop));
+								}
+								params[i] = converter.from(strparams[i]);
+							}
+						}
+					}
+					try {
+						method.invoke(bean, params);
+						ret.add(method.getName());
+					} catch (IllegalArgumentException e) {
+						throw new MagmaException(e, "There has been an error calling {0}.{1} using late configuration {2}", method.getDeclaringClass(), method.getName(), Arrays.toString(prop));
+					} catch (IllegalAccessException e) {
+						throw new MagmaException(e, "Method {0}.{1} is not accessible", method.getDeclaringClass(), method.getName());
+					} catch (InvocationTargetException e) {
+						throw new MagmaException(e, "There has been an error calling {0}.{1} using late configuration {2}", method.getDeclaringClass(), method.getName(), Arrays.toString(prop));					
+					}
+				}
+			}
+			return ret;
+		} catch (Exception e) {
+			if (prop != null) {
+				throw new MagmaException(e, "Error while executing late config for {0}, on line {1}", bean.getClass(), Arrays.toString(prop));
+			} else {
+				throw new MagmaException(e, "Error while executing late config for {0}", bean.getClass());				
+			}
+		} finally {
+			RunningContext.get().popClass();
+		}
+	}
+
+	protected static String[] parseArguments(String val, String[] props) {
+		String[] strparams = val.split(",");
+		// Let's try to handle string in quotes
+		int quoteindex = -1;
+		do {
+			quoteindex = -1;
+			int quotedcount = 0;
+			boolean closed = false;
+			for (int i = 0; i < strparams.length; i++) {
+				if (quoteindex == -1) {
+					if (strparams[i].startsWith("\"")) {
+						strparams[i] = strparams[i].substring(1);
+						quoteindex = i;
+					}
+				} else {
+					if (strparams[i].endsWith("\"")) {
+						closed = true;
+						strparams[i] = strparams[i].substring(0, strparams[i].length() - 1);
+					}
+					quotedcount++;
+					strparams[quoteindex] += "," + strparams[i];
+					strparams[i] = null;
+					if (closed) break;
+				}
+			}
+			if (quoteindex != -1 && !closed) throw new MagmaException("Unclosed \" in lateconfig.properties {0}", Arrays.toString(props));
+			String[] nstrparams = new String[strparams.length - quotedcount];
+			int k = 0;
+			for (int i = 0; i < strparams.length; i++) {
+				if (strparams[i] != null) nstrparams[k++] = strparams[i];
+			}						
+			strparams = nstrparams;
+		} while (quoteindex > -1);
+		return strparams;
+	}
+	
+	protected static ContextSettingsHolder initSettings() {
+		ContextSettingsHolder holder = null;
+		if (Settings.isDeveloperEnv()) {
+			holder = devholder.get();
+			if (holder == null) {
+				holder = new ContextSettingsHolder();
+				devholder.set(holder);
+			}
+			// No double check, cycle is thread specific
+			if (holder.isInited()) return holder;
+			holder.initing();
+			initHolder(holder);
+		} else {
+			holder = prodholder;
+			if (holder.isInited()) return holder;
+			holder.initing();
+			if (holder.isInited()) return holder;
+			initHolder(holder);
+		}
+		return holder;
+	}
+	
+	protected static void initHolder(ContextSettingsHolder holder) {
+		ClassLoader loader = holder.getClass().getClassLoader();
+		Enumeration<URL> resources;
+		try {
+			resources = loader.getResources("META-INF/lateconfig.default.properties");
+			while (resources.hasMoreElements()) {
+				holder.overrideWith(resources.nextElement());
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		try {
+			resources = loader.getResources("META-INF/lateconfig.default.properties.xml");
+			while (resources.hasMoreElements()) {
+				holder.overrideWith(resources.nextElement());
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		holder.overrideWith(loader.getResource("META-INF/lateconfig.properties"));
+		holder.overrideWith(loader.getResource("META-INF/lateconfig.properties.xml"));
+		holder.inited();		
+	}
+	
+	
+}

Added: labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/LateConfigBean.java
URL: http://svn.apache.org/viewvc/labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/LateConfigBean.java?rev=882441&view=auto
==============================================================================
--- labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/LateConfigBean.java (added)
+++ labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/LateConfigBean.java Fri Nov 20 08:06:23 2009
@@ -0,0 +1,59 @@
+package org.apache.magma.lateconfig;
+
+import java.lang.annotation.ElementType;
+
+@LateConfigurable
+public class LateConfigBean {
+
+	private String stringProp;
+	private String chained;
+	private String twostrings;
+	private int exoticInt;
+	private ElementType exoticEnum;
+
+	@LateConfigurationTrigger
+	public LateConfigBean() {
+		
+	}
+		
+	public String getStringProp() {
+		return stringProp;
+	}
+
+	@LateConfigurable
+	public void setStringProp(String stringProp) {
+		this.stringProp = stringProp;
+	}
+
+	public String getChained() {
+		return chained;
+	}
+
+	@LateConfigurable
+	public LateConfigBean setChained(String chained) {
+		this.chained = chained;
+		return this;
+	}
+	
+	@LateConfigurable
+	public void setTwoStrings(String a, String b) {
+		twostrings = a + "-" + b; 
+	}
+	public String getTwostrings() {
+		return twostrings;
+	}
+	
+	@LateConfigurable
+	public void exotic(int i, ElementType ele) {
+		exoticEnum=ele;
+		exoticInt=i;
+	}
+
+	public int getExoticInt() {
+		return exoticInt;
+	}
+
+	public ElementType getExoticEnum() {
+		return exoticEnum;
+	}
+}

Added: labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/LateConfigTest.java
URL: http://svn.apache.org/viewvc/labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/LateConfigTest.java?rev=882441&view=auto
==============================================================================
--- labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/LateConfigTest.java (added)
+++ labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/LateConfigTest.java Fri Nov 20 08:06:23 2009
@@ -0,0 +1,101 @@
+package org.apache.magma.lateconfig;
+
+import static org.junit.Assert.*;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+
+import org.apache.magma.basics.MagmaException;
+import org.apache.magma.basics.context.RunningContext;
+import org.apache.magma.basics.context.SubRunningContext;
+import org.junit.After;
+import org.junit.Test;
+
+public class LateConfigTest {
+	
+	@Test
+	public void plainConfigure() throws Exception {
+		LateConfigBean bean = new LateConfigBean();
+		assertEquals("Simple configuration not working", "configured correctly", bean.getStringProp());
+	}
+
+	@After
+	public void cleanContext() {
+		RunningContext.cleanup();
+	}
+	
+	@Test
+	public void differentContext() throws Exception {
+		SubRunningContext src = RunningContext.get();
+		src.push("incontext");
+		
+		LateConfigBean bean = new LateConfigBean();
+		assertEquals("in context configuration not working", "configured in context", bean.getStringProp());
+	}
+	
+	@Test
+	public void avoidSettingAgain() throws Exception {
+		LateConfigBean bean = new LateConfigBean();
+		assertEquals("Simple configuration not working", "configured correctly", bean.getStringProp());
+		bean.setStringProp("should not go");
+		assertEquals("Java set interception not working", "configured correctly", bean.getStringProp());
+	}
+	
+	@Test
+	public void chainedSetters() throws Exception {
+		LateConfigBean bean = new LateConfigBean();
+		assertEquals("Simple configuration not working", "configured correctly", bean.getStringProp());
+		assertEquals("Simple configuration not working", "Configured Correctly", bean.getChained());
+		// If throws exception here it is not chaining
+		bean.setChained("no go").setStringProp("should not go");
+		assertEquals("Java set interception not working", "configured correctly", bean.getStringProp());
+		assertEquals("Java set interception not working", "Configured Correctly", bean.getChained());
+	}
+	
+	@Test
+	public void otherTrigger() throws Exception {
+		OtherTriggerBean bean = new OtherTriggerBean();
+		assertEquals("Configured during constructor", "empty", bean.getStringProp());
+		String compute = bean.compute();
+		assertEquals("Not configured before trigger execution", "configured correctly", compute);
+	}
+	
+	@Test
+	public void parseParamsTest() throws Exception {
+		String[] parsed = LateConfigurator.parseArguments("a,b", new String[0]);
+		assertEquals(2, parsed.length);
+		assertEquals("a", parsed[0]);
+		assertEquals("b", parsed[1]);
+	}
+	
+	@Test
+	public void quotedParamsTest() throws Exception {
+		String[] parsed = LateConfigurator.parseArguments("\"a,b,c\",d", new String[0]);
+		assertEquals(2, parsed.length);
+		assertEquals("a,b,c", parsed[0]);
+		assertEquals("d", parsed[1]);
+	}
+	
+	@Test
+	public void multipleParameters() throws Exception {
+		LateConfigBean bean = new LateConfigBean();
+		assertEquals("Multiple parameters not working correctly", "configured-it", bean.getTwostrings());
+	}
+	
+	@Test(expected=MagmaException.class)
+	public void multipleParametersWithFewParameters() throws Exception {
+		SubRunningContext src = RunningContext.get();
+		src.push("wrongmulti");
+		LateConfigBean bean = new LateConfigBean();		
+	}
+	
+	@Test
+	public void exoticSetter() throws Exception {
+		SubRunningContext src = RunningContext.get();
+		src.push("inexotic");
+		LateConfigBean bean = new LateConfigBean();		
+		assertEquals("Exotic set of int failed", 5, bean.getExoticInt());
+		assertEquals("Exotic set of enum failed", ElementType.METHOD, bean.getExoticEnum());
+	}
+
+}

Added: labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/OtherTriggerBean.java
URL: http://svn.apache.org/viewvc/labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/OtherTriggerBean.java?rev=882441&view=auto
==============================================================================
--- labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/OtherTriggerBean.java (added)
+++ labs/magma/trunk/lateconfig-impl/src/test/java/org/apache/magma/lateconfig/OtherTriggerBean.java Fri Nov 20 08:06:23 2009
@@ -0,0 +1,21 @@
+package org.apache.magma.lateconfig;
+
+@LateConfigurable
+public class OtherTriggerBean {
+	private String stringProp = "empty";
+
+	public String getStringProp() {
+		return stringProp;
+	}
+
+	@LateConfigurable
+	public void setStringProp(String stringProp) {
+		this.stringProp = stringProp;
+	}
+	
+	@LateConfigurationTrigger
+	public String compute() {
+		return this.stringProp;
+	}
+
+}

Added: labs/magma/trunk/lateconfig-impl/src/test/resources/META-INF/lateconfig.properties
URL: http://svn.apache.org/viewvc/labs/magma/trunk/lateconfig-impl/src/test/resources/META-INF/lateconfig.properties?rev=882441&view=auto
==============================================================================
--- labs/magma/trunk/lateconfig-impl/src/test/resources/META-INF/lateconfig.properties (added)
+++ labs/magma/trunk/lateconfig-impl/src/test/resources/META-INF/lateconfig.properties Fri Nov 20 08:06:23 2009
@@ -0,0 +1,6 @@
+stringProp=configured correctly
+incontext.stringProp=configured in context
+chained=Configured Correctly
+twostrings=configured,it
+wrongmulti.twostrings=configured
+inexotic.exotic=5,METHOD
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org