MentaContainer

Compare Revisions

Ignore whitespace Rev 1 → Rev HEAD

/trunk/src/test/java/org/mentacontainer/impl/GenericFactoryTest.java
New file
0,0 → 1,45
package org.mentacontainer.impl;
 
import junit.framework.Assert;
 
import org.junit.Test;
import org.mentacontainer.Factory;
import org.mentacontainer.Container;
import org.mentacontainer.impl.GenericFactory;
import org.mentacontainer.impl.MentaContainer;
 
public class GenericFactoryTest {
public static class SomeFactory {
public String giveMeSomething() {
return String.valueOf(System.nanoTime());
}
}
@Test
public void testGenericFactory() throws Exception {
// in real life this will be a SessionFactory, a ConnectionPool or any factory...
SomeFactory factory = new SomeFactory();
Container c = new MentaContainer();
// giveMeSomething => method that will be called to return object
Factory generic = new GenericFactory(factory, "giveMeSomething");
c.ioc("myFactory", generic);
String s1 = c.get("myFactory");
Thread.sleep(5); // so strings are different... my cpu is fast! :-)
String s2 = c.get("myFactory");
Assert.assertNotNull(s1);
Assert.assertNotNull(s2);
Assert.assertTrue(s1 != s2);
Assert.assertTrue(!s1.equals(s2));
}
}
/trunk/src/test/java/org/mentacontainer/impl/MentaContainerTest.java
New file
0,0 → 1,535
package org.mentacontainer.impl;
 
import junit.framework.Assert;
 
import org.junit.Test;
import org.mentacontainer.Interceptor;
import org.mentacontainer.Factory;
import org.mentacontainer.Container;
import org.mentacontainer.Scope;
 
public class MentaContainerTest {
 
@Test
public void testSimpleGet() {
 
Container c = new MentaContainer();
 
c.ioc("myStr", String.class);
 
Assert.assertEquals("", c.get("myStr"));
 
String s1 = c.get("myStr");
 
String s2 = c.get("myStr");
 
Assert.assertTrue(s1 != s2);
 
Assert.assertTrue(s1.equals(s2));
}
 
@Test
public void testConstructorInit() {
 
Container c = new MentaContainer();
 
c.ioc("myStr", String.class).addInitValue("hello");
 
Assert.assertEquals("hello", c.get("myStr"));
 
String s1 = c.get("myStr");
 
String s2 = c.get("myStr");
 
Assert.assertTrue(s1 != s2);
 
Assert.assertTrue(s1.equals(s2));
 
c.ioc("anotherStr", String.class).addInitValue("hi");
 
String s3 = c.get("anotherStr");
 
Assert.assertTrue(s1 != s3);
 
Assert.assertFalse(s1.equals(s3));
}
 
@Test
public void testSingleton() {
 
Container c = new MentaContainer();
 
c.ioc("myStr", String.class, Scope.SINGLETON).addInitValue("hello");
 
Assert.assertEquals("hello", c.get("myStr"));
 
String s1 = c.get("myStr");
 
String s2 = c.get("myStr");
 
Assert.assertTrue(s1 == s2);
 
Assert.assertTrue(s1.equals(s2));
}
@Test
public void testCheckAndClear() {
Container c = new MentaContainer();
c.ioc("myStr", String.class, Scope.SINGLETON).addInitValue("hello");
 
Assert.assertEquals(false, c.check("myStr"));
String s1 = c.get("myStr");
Assert.assertEquals(true, c.check("myStr"));
String s2 = c.get("myStr");
Assert.assertTrue(s1 == s2);
c.clear(Scope.SINGLETON);
Assert.assertEquals(false, c.check("myStr"));
String s3 = c.get("myStr");
Assert.assertTrue(s3 != s2);
}
private static class MyThread extends Thread {
private final Container c;
private final String key;
private String value = null;
public MyThread(Container c, String key) {
super();
this.c = c;
this.key = key;
}
@Override
public void run() {
for(int i = 0; i < 50; i++) {
String v = c.get(key);
if (this.value != null) {
Assert.assertTrue(this.value == v);
}
this.value = v;
}
}
public String getValue() { return value; }
}
@Test
public void testScopes() {
Container c = new MentaContainer();
// if you don't provide a scope the Scope is NONE
// meaning a new instance is created on every
// request for the bean
c.ioc("myString", String.class).addInitValue("saoj");
String s1 = c.get("myString");
String s2 = c.get("myString");
Assert.assertTrue(s1 != s2);
// then you can use SINGLETON
// always get the same instance no matter what
c.ioc("myString", String.class, Scope.SINGLETON).addInitValue("saoj");
s1 = c.get("myString");
s2 = c.get("myString");
Assert.assertTrue(s1 == s2);
// then you can use THREAD
// each thread will get a different instance
c.ioc("myString", String.class, Scope.THREAD).addInitValue("saoj");
s1 = c.get("myString");
s2 = c.get("myString");
Assert.assertTrue(s1 == s2); // same thread
}
@Test
public void testThreadLocal() throws Exception {
final Container c = new MentaContainer();
c.ioc("myStr", String.class, Scope.THREAD).addInitValue("saoj");
String s1 = c.get("myStr");
MyThread t1 = new MyThread(c, "myStr");
MyThread t2 = new MyThread(c, "myStr");
t1.start();
t2.start();
t1.join();
t2.join();
String s2 = t1.getValue();
String s3 = t2.getValue();
Assert.assertTrue(s1 != s2);
Assert.assertTrue(s2 != s3);
}
 
public static interface MyDAO {
public Object getSomething();
}
public static class SomeDependency {
private String name;
public SomeDependency() { }
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static class Connection {
private final String name;
private SomeDependency dep;
public Connection(String name) {
this.name = name;
}
@Override
public String toString() {
return getClass().getName() + ": " + name;
}
public String getName() { return name; }
public void setMyDep(SomeDependency dep) { this.dep = dep; }
public SomeDependency getMyDep() { return dep; }
}
public static class JdbcMyDAO implements MyDAO {
private Connection conn;
public void setConnection(Connection conn) { this.conn = conn; }
public Connection getConnection() { return conn; }
@Override
public Object getSomething() {
// use the connection to do something...
Assert.assertNotNull(conn); // it cannot be null!
// also test if the connection also received the myDep dependency...
Assert.assertNotNull(conn.getMyDep());
return conn.toString();
}
}
private Container getConfiguredContainer() {
Container c = new MentaContainer();
c.ioc("myDAO", JdbcMyDAO.class);
c.ioc("aDependency", SomeDependency.class, Scope.SINGLETON).addPropertyValue("name", "A super dependency!");
c.ioc("connection", Connection.class).addInitValue("A super JDBC connection!");
c.autowire("connection");
c.autowire("aDependency", "myDep");
return c;
}
@Test
public void testAutoWiring() {
Container c = getConfiguredContainer();
MyDAO myDAO = c.get("myDAO");
// check implementation...
Assert.assertEquals(JdbcMyDAO.class, myDAO.getClass());
// check dependency...
Connection conn = ((JdbcMyDAO) myDAO).getConnection();
Assert.assertNotNull(conn);
Assert.assertEquals("A super JDBC connection!", conn.getName());
// check dependency of dependency...
Assert.assertEquals(c.get("aDependency"), conn.getMyDep());
Assert.assertTrue(c.get("aDependency") == conn.getMyDep()); // singleton!
// check DAO can do its job...
Assert.assertNotNull(myDAO.getSomething());
}
public static class MyObject1 {
}
public static class MyObject2 {
}
public static class MyObject3 {
public MyObject3(MyObject2 o2, MyObject1 o1) {
 
}
}
private Container getConfiguredContainer2() {
Container c = new MentaContainer();
c.ioc("myObj1", MyObject1.class);
c.ioc("myObj2", MyObject2.class);
c.ioc("myObj3", MyObject3.class);
c.autowire("myObj1");
c.autowire("myObj2");
return c;
}
@Test
public void testAutoWiringWithTwoConstructors() {
Container c = getConfiguredContainer2();
MyObject3 obj3 = c.get("myObj3");
Assert.assertNotNull(obj3);
}
public static class SomeAction {
private MyDAO myDAO = null;
public void setMyDAO(MyDAO myDAO) {
this.myDAO = myDAO;
}
public MyDAO getMyDAO() { return myDAO; }
}
@Test
public void testPopulate() {
Container c = getConfiguredContainer();
SomeAction a = new SomeAction();
c.inject(a); // great... properties of SomeAction were populated by container...
// let's check if myDAO was injected...
Assert.assertNotNull(a.getMyDAO());
// also check if myDAO was corrected wired...
Connection conn = ((JdbcMyDAO) a.getMyDAO()).getConnection();
Assert.assertNotNull(conn);
// check if conn was also wired...
Assert.assertNotNull(conn.getMyDep());
}
public static class SomeAction2 {
private final MyDAO myDAO;
public SomeAction2(MyDAO myDAO) {
this.myDAO = myDAO;
}
public MyDAO getMyDAO() { return myDAO; }
}
@Test
public void testConstructorDependency() {
Container c = new MentaContainer();
c.ioc("myDAO", JdbcMyDAO.class);
c.ioc("aDependency", SomeDependency.class, Scope.SINGLETON).addPropertyValue("name", "A super dependency!");
c.ioc("connection", Connection.class).addInitValue("A super JDBC connection!");
c.autowire("connection");
c.autowire("aDependency", "myDep");
c.ioc("someAction2", SomeAction2.class).addConstructorDependency("myDAO");
SomeAction2 action = c.get("someAction2");
Assert.assertNotNull(action.getMyDAO());
}
@Test
public void testConstruct() {
Container c = getConfiguredContainer();
SomeAction2 a = c.construct(SomeAction2.class);
// let's check if myDAO was injected...
Assert.assertNotNull(a.getMyDAO());
// also check if myDAO was corrected wired...
Connection conn = ((JdbcMyDAO) a.getMyDAO()).getConnection();
Assert.assertNotNull(conn);
// check if conn was also wired...
Assert.assertNotNull(conn.getMyDep());
}
private static class SomeObject {
private boolean destroyed = false;
private boolean created = false;
public void destroyed() { this.destroyed = true; }
public boolean isDestroyed() { return destroyed; }
public void created() { this.created = true; }
public boolean isCreated() { return created; }
}
private static class SomeFactory implements Factory, Interceptor<SomeObject> {
@Override
public <T> T getInstance() {
return (T) new SomeObject();
}
@Override
public Class<?> getType() {
return SomeObject.class;
}
@Override
public void onCleared(SomeObject obj) {
obj.destroyed();
}
@Override
public void onCreated(SomeObject obj) {
obj.created();
}
}
@Test
public void testInterceptor() {
Container c = new MentaContainer();
c.ioc("o", new SomeFactory(), Scope.SINGLETON);
SomeObject o = c.get("o");
Assert.assertTrue(o.isCreated());
c.clear(Scope.SINGLETON);
Assert.assertEquals(true, o.isDestroyed());
c.ioc("o", new SomeFactory(), Scope.THREAD);
o = c.get("o");
Assert.assertTrue(o.isCreated());
c.clear(Scope.SINGLETON);
Assert.assertEquals(false, o.isDestroyed());
c.clear(Scope.THREAD);
Assert.assertEquals(true, o.isDestroyed());
c.ioc("o", new SomeFactory(), Scope.NONE);
o = c.get("o");
Assert.assertTrue(o.isCreated());
o = c.clear("o");
Assert.assertNull(o);
c.ioc("o", new SomeFactory(), Scope.THREAD);
o = c.clear("o");
Assert.assertNull(o);
o = c.get("o");
Assert.assertTrue(o.isCreated());
o = c.clear("o");
Assert.assertEquals(true, o.isDestroyed());
}
}
/trunk/src/test/java/org/mentacontainer/impl/WrapperFactoryTest.java
New file
0,0 → 1,31
package org.mentacontainer.impl;
 
import junit.framework.Assert;
 
import org.junit.Test;
import org.mentacontainer.Factory;
import org.mentacontainer.Container;
 
public class WrapperFactoryTest {
@Test
public void testInstanceFactory() throws Exception {
String s = new String("saoj");
Factory ic = new SingletonFactory(s);
Container c = new MentaContainer();
c.ioc("myString", ic);
String s1 = c.get("myString");
String s2 = c.get("myString");
Assert.assertNotNull(s1);
Assert.assertNotNull(s2);
Assert.assertTrue(s == s1);
Assert.assertTrue(s1 == s2);
}
}
/trunk/src/test/java/org/mentacontainer/impl/ClassFactoryTest.java
New file
0,0 → 1,290
package org.mentacontainer.impl;
 
import junit.framework.Assert;
 
import org.junit.Test;
import org.mentacontainer.Factory;
 
public class ClassFactoryTest {
private static class User {
private String username;
public User() { }
public User(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
@Test
public void testFactory() {
MentaContainer container = new MentaContainer();
Factory c1 = new ClassFactory(container, User.class).addInitValue("saoj");
Factory c2 = new ClassFactory(container, User.class).addPropertyValue("username", "soliveira");
User u1 = c1.getInstance();
User u2 = c2.getInstance();
Assert.assertTrue(u1 != u2);
Assert.assertTrue(!u1.getUsername().equals(u2.getUsername()));
}
private static class TestObj1 {
String s;
int i;
long l;
User u;
public TestObj1(String s, int i, long l, User u) {
this.s = s;
this.i = i;
this.l = l;
this.u = u;
}
}
@Test
public void testDependable1() {
MentaContainer c = new MentaContainer();
c.ioc("myString", String.class).addInitValue("hello");
Factory c1 = new ClassFactory(c, TestObj1.class).addConstructorDependency("myString").addInitValue(20).addInitValue(30000L)
.addInitValue(new User("saoj"));
TestObj1 o = c1.getInstance();
Assert.assertEquals("hello", o.s);
Assert.assertEquals(20, o.i);
Assert.assertEquals(30000L, o.l);
Assert.assertEquals("saoj", o.u.getUsername());
}
private static class TestObj1_1 {
String s;
int i;
public TestObj1_1() { }
public void setS(String s) { this.s = s; }
public void setI(int i) { this.i = i; }
}
 
@Test
public void testDependable2() {
MentaContainer c = new MentaContainer();
c.ioc("myString", String.class).addInitValue("hello");
Factory c1 = new ClassFactory(c, TestObj1_1.class).addPropertyDependency("s", "myString").addPropertyValue("i", 30);
TestObj1_1 o = c1.getInstance();
Assert.assertEquals("hello", o.s);
Assert.assertEquals(30, o.i);
}
private static class TestObj2 {
int x;
public TestObj2() { }
public void setInteger(int x) {
this.x = x;
}
}
@Test
public void testPrimitivePropertyValue1() {
MentaContainer container = new MentaContainer();
Factory f = new ClassFactory(container, TestObj2.class).addPropertyValue("integer", 20);
TestObj2 o = f.getInstance();
Assert.assertEquals(20, o.x);
}
@Test
public void testPrimitivePropertyValue2() {
MentaContainer container = new MentaContainer();
Factory f = new ClassFactory(container, TestObj2.class).addPropertyValue("integer", new Integer(20));
TestObj2 o = f.getInstance();
Assert.assertEquals(20, o.x);
}
private static class TestObj2_1 {
int x;
public TestObj2_1() { }
public void setInteger(Integer x) {
this.x = x;
}
}
@Test
public void testPrimitivePropertyValue3() {
MentaContainer container = new MentaContainer();
Factory f = new ClassFactory(container, TestObj2_1.class).addPropertyValue("integer", 20);
TestObj2_1 o = f.getInstance();
Assert.assertEquals(20, o.x);
}
@Test
public void testPrimitivePropertyValue4() {
MentaContainer container = new MentaContainer();
Factory f = new ClassFactory(container, TestObj2_1.class).addPropertyValue("integer", new Integer(20));
TestObj2_1 o = f.getInstance();
Assert.assertEquals(20, o.x);
}
private static class TestObj3 {
int x;
public TestObj3(int x) {
this.x = x;
}
}
@Test
public void testPrimitiveInitValue1() {
MentaContainer container = new MentaContainer();
Factory f = new ClassFactory(container, TestObj3.class).addInitValue(20);
TestObj3 o = f.getInstance();
Assert.assertEquals(20, o.x);
}
private static class TestObj3_1 {
int x;
public TestObj3_1(Integer x) {
this.x = x;
}
}
@Test
public void testPrimitiveInitValue2() {
MentaContainer container = new MentaContainer();
Factory f = new ClassFactory(container, TestObj3_1.class).addInitValue(20);
TestObj3_1 o = f.getInstance();
Assert.assertEquals(20, o.x);
}
private static class TestObj3_2 {
int x;
long l;
public TestObj3_2(Integer x, long l) {
this.x = x;
this.l = l;
}
}
@Test
public void testPrimitiveInitValue3() {
MentaContainer container = new MentaContainer();
Factory f = new ClassFactory(container, TestObj3_2.class).addInitValue(20).addInitPrimitive(30L);
TestObj3_2 o = f.getInstance();
Assert.assertEquals(20, o.x);
Assert.assertEquals(30L, o.l);
}
private static class TestObj4 {
int x;
String s;
Long l1;
long l2;
public TestObj4(int x, String s, Long l1, long l2) {
this.x = x;
this.s = s;
this.l1 = l1;
this.l2 = l2;
}
}
@Test
public void testMixInitValues() {
MentaContainer container = new MentaContainer();
Factory f = new ClassFactory(container, TestObj4.class).addInitPrimitive(20).addInitValue("hello").addInitValue(20L).addInitPrimitive(20L);
TestObj4 o = f.getInstance();
Assert.assertEquals(20, o.x);
Assert.assertEquals("hello", o.s);
Assert.assertEquals(new Long(20), o.l1);
Assert.assertEquals(20, o.l2);
}
private static class TestObj22 {
public TestObj22() { }
}
@Test
public void testOnlyOneZeroArgConstructor() {
MentaContainer container = new MentaContainer();
Factory f = new ClassFactory(container, TestObj22.class);
TestObj22 o = f.getInstance();
Assert.assertNotNull(o);
}
}
/trunk/src/test/java/org/mentacontainer/example/CoreExamplesTest.java
New file
0,0 → 1,198
package org.mentacontainer.example;
 
import java.util.Calendar;
import java.util.Date;
 
import junit.framework.Assert;
 
import org.junit.Test;
import org.mentacontainer.Container;
import org.mentacontainer.impl.MentaContainer;
 
public class CoreExamplesTest {
@Test
public void testBeanInitialization() {
Container c = new MentaContainer();
c.ioc("myString1", String.class);
String myString1 = c.get("myString1");
Assert.assertEquals("", myString1); // default constructor...
c.ioc("myString2", String.class).addInitValue("saoj");
String myString2 = c.get("myString2"); // using constructor....
Assert.assertEquals("saoj", myString2);
Assert.assertNotSame(c.get("myString1"), c.get("myString1")); // most be different instances...
// test setters...
c.ioc("myDate1", Date.class).addPropertyValue("hours", 15) // setHours(15)
.addPropertyValue("minutes", 10) // setMinutes(10)
.addPropertyValue("seconds", 45); // setSeconds(45)
Date myDate1 = c.get("myDate1");
Assert.assertTrue(myDate1.toString().indexOf("15:10:45") > 0);
// test setter together with constructor...
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1976);
c.ioc("myDate2", Date.class).addInitValue(cal.getTimeInMillis()).addPropertyValue("seconds", 59);
Date myDate2 = c.get("myDate2");
Assert.assertTrue(myDate2.toString().indexOf(":59") > 0);
Assert.assertTrue(myDate2.toString().indexOf("1976") > 0);
}
@Test
public void testDependencies() {
// constructor dependency...
Container c = new MentaContainer();
c.ioc("username", String.class).addInitValue("saoj");
 
c.ioc("myString", String.class).addConstructorDependency("username");
String myString = c.get("myString");
Assert.assertEquals("saoj", myString);
// setter dependency...
c.ioc("myBirthdayYear", Integer.class).addInitValue(76);
c.ioc("myBirthday", Date.class).addPropertyDependency("year", "myBirthdayYear").addPropertyValue("month", 0).addPropertyValue("date", 20);
Date myBirthday = c.get("myBirthday");
Assert.assertTrue(myBirthday.toString().indexOf("Jan 20") > 0);
Assert.assertTrue(myBirthday.toString().indexOf("1976") > 0);
// both...
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1976);
 
c.ioc("timeInMillis", Long.class).addInitValue(cal.getTimeInMillis());
c.ioc("myBirthdayMonth", Integer.class).addInitValue(0);
c.ioc("myBirthday", Date.class).addConstructorDependency("timeInMillis").addPropertyDependency("month", "myBirthdayMonth").addPropertyValue("date", 20);
myBirthday = c.get("myBirthday");
Assert.assertTrue(myBirthday.toString().indexOf("Jan 20") > 0);
Assert.assertTrue(myBirthday.toString().indexOf("1976") > 0);
}
@Test
public void testAutoWiring() {
// constructor dependency...
Container c = new MentaContainer();
c.ioc("username", String.class).addInitValue("saoj");
 
c.ioc("myString", String.class);
c.autowire("username");
String myString = c.get("myString");
Assert.assertEquals("saoj", myString);
// setter dependency...
c = new MentaContainer();
c.ioc("myBirthdayYear", Integer.class).addInitValue(76);
c.ioc("myBirthday", Date.class).addPropertyValue("month", 0).addPropertyValue("date", 20);
c.autowire("myBirthdayYear", "year");
Date myBirthday = c.get("myBirthday");
Assert.assertTrue(myBirthday.toString().indexOf("Jan 20") > 0);
Assert.assertTrue(myBirthday.toString().indexOf("1976") > 0);
// both...
c = new MentaContainer();
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1976);
 
c.ioc("timeInMillis", Long.class).addInitValue(cal.getTimeInMillis());
c.ioc("myBirthdayMonth", Integer.class).addInitValue(0);
c.ioc("myBirthday", Date.class).addPropertyValue("date", 20);
c.autowire("timeInMillis");
c.autowire("myBirthdayMonth", "month");
myBirthday = c.get("myBirthday");
Assert.assertTrue(myBirthday.toString().indexOf("Jan 20") > 0);
Assert.assertTrue(myBirthday.toString().indexOf("1976") > 0);
// bypass autowireByConstructor by specifying...
c = new MentaContainer();
cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1976);
 
Calendar cal2 = Calendar.getInstance();
cal2.set(Calendar.YEAR, 1977);
c.ioc("timeInMillis", Long.class).addInitValue(cal.getTimeInMillis());
c.ioc("timeInMillis2", Long.class).addInitValue(cal2.getTimeInMillis());
c.ioc("myBirthdayMonth", Integer.class).addInitValue(0);
c.ioc("myBirthday", Date.class).addPropertyValue("date", 20).addConstructorDependency("timeInMillis2");
c.autowire("timeInMillis");
c.autowire("myBirthdayMonth", "month");
myBirthday = c.get("myBirthday");
Assert.assertTrue(myBirthday.toString().indexOf("Jan 20") > 0);
Assert.assertTrue(myBirthday.toString().indexOf("1977") > 0);
// bypass autowireBySetter by specifying...
// not supported yet...
// force zero arguments constructor...
c = new MentaContainer();
cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1976);
 
c.ioc("timeInMillis", Long.class).addInitValue(cal.getTimeInMillis());
c.ioc("myBirthdayMonth", Integer.class).addInitValue(0);
c.ioc("myBirthday", Date.class).addPropertyValue("date", 20).useZeroArgumentConstructor();
c.autowire("timeInMillis");
c.autowire("myBirthdayMonth", "month");
myBirthday = c.get("myBirthday");
Assert.assertTrue(myBirthday.toString().indexOf("Jan 20") > 0);
Assert.assertTrue(myBirthday.toString().indexOf("1976") == -1);
}
}
/trunk/src/main/java/org/mentacontainer/impl/ConstructorDependency.java
New file
0,0 → 1,54
package org.mentacontainer.impl;
 
 
/**
* A simple implementation of the Dependency interface.
*
* @author sergio.oliveira.jr@gmail.com
*/
class ConstructorDependency {
private final String sourceFromContainer;
private final Class<?> sourceType;
public ConstructorDependency(String sourceFromContainer, Class<?> sourceType) {
this.sourceFromContainer = sourceFromContainer;
this.sourceType = sourceType;
}
public String getSource() {
return sourceFromContainer;
}
public Class<?> getSourceType() {
return sourceType;
}
@Override
public int hashCode() {
return sourceFromContainer.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ConstructorDependency)) return false;
ConstructorDependency d = (ConstructorDependency) obj;
if (!d.sourceFromContainer.equals(this.sourceFromContainer)) return false;
return true;
}
@Override
public String toString() {
return "[ConstructorDependency: sourceFromContainer=" + sourceFromContainer + "]";
}
}
/trunk/src/main/java/org/mentacontainer/impl/GenericFactory.java
New file
0,0 → 1,74
package org.mentacontainer.impl;
 
import java.lang.reflect.Method;
 
import org.mentacontainer.Factory;
import org.mentacontainer.Interceptor;
import org.mentacontainer.util.FindMethod;
 
public class GenericFactory<E> implements Factory, Interceptor<E> {
private final Object factory;
private final Method method;
private final Class<?> type;
private Interceptor<E> interceptor = null;
public GenericFactory(Object factory, String methodName) {
this.factory = factory;
try {
this.method = FindMethod.getMethod(factory.getClass(), methodName, new Class[] { });
this.method.setAccessible(true);
this.type = method.getReturnType();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
public void setInterceptor(Interceptor<E> interceptor) {
this.interceptor = interceptor;
}
@Override
public void onCreated(E createdObject) {
if (interceptor != null) {
interceptor.onCreated(createdObject);
}
}
@Override
public void onCleared(E clearedObject) {
if (interceptor != null) {
interceptor.onCleared(clearedObject);
}
}
@Override
public <T> T getInstance() {
try {
return (T) method.invoke(factory, (Object[]) null);
} catch(Exception e) {
throw new RuntimeException("Cannot invoke method: " + method, e);
}
}
@Override
public Class<?> getType() {
return type;
}
}
/trunk/src/main/java/org/mentacontainer/impl/SetterDependency.java
New file
0,0 → 1,141
package org.mentacontainer.impl;
 
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
 
import org.mentacontainer.util.InjectionUtils;
 
/**
* A simple implementation of the Dependency interface.
*
* @author sergio.oliveira.jr@gmail.com
*/
class SetterDependency {
private final String targetProperty;
private final String sourceFromContainer;
private final Class<?> sourceType;
private Map<String, Method> cache = new HashMap<String, Method>();
public SetterDependency(String targetProperty, String sourceFromContainer, Class<?> sourceType) {
this.targetProperty = targetProperty;
this.sourceFromContainer = sourceFromContainer;
this.sourceType = sourceType;
}
public String getTarget() {
return targetProperty;
}
public String getSource() {
return sourceFromContainer;
}
@Override
public int hashCode() {
return targetProperty.hashCode() * 31 + sourceFromContainer.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SetterDependency)) return false;
SetterDependency d = (SetterDependency) obj;
if (!d.targetProperty.equals(this.targetProperty)) return false;
if (!d.sourceFromContainer.equals(this.sourceFromContainer)) return false;
return true;
}
public Method check(Class<?> targetClass) {
 
String className = targetClass.getName();
 
// first check cache...
Method m = null;
synchronized(cache) {
m = cache.get(className);
}
if (m == null && cache.containsKey(className)) return null; // it is null...
 
if (m != null) return m;
 
m = InjectionUtils.findMethodToInject(targetClass, targetProperty, sourceType);
/*
try {
Method[] methods = targetClass.getMethods();
StringBuilder sb = new StringBuilder(128);
sb.append("set");
sb.append(targetProperty.substring(0, 1).toUpperCase());
if (targetProperty.length() > 1) sb.append(targetProperty.substring(1));
String methodName = sb.toString();
for(Method theMethod : methods) {
if (theMethod.getName().equals(methodName)) {
// check type...
Class<?>[] params = theMethod.getParameterTypes();
if (params == null || params.length != 1) continue;
if (params[0].isAssignableFrom(sourceType)) {
m = theMethod;
break;
}
}
}
} catch(Exception e) {
e.printStackTrace();
}
*/
if (m != null) {
synchronized(cache) {
 
cache.put(className, m);
}
return m;
}
synchronized(cache) {
// save null to indicate there is no method here... (so you don't do again to find null !!!
cache.put(className, null);
}
 
return null;
}
}
/trunk/src/main/java/org/mentacontainer/impl/MentaContainer.java
New file
0,0 → 1,556
package org.mentacontainer.impl;
 
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
import org.mentacontainer.ConfigurableFactory;
import org.mentacontainer.Container;
import org.mentacontainer.Factory;
import org.mentacontainer.Interceptor;
import org.mentacontainer.Scope;
import org.mentacontainer.util.InjectionUtils;
import org.mentacontainer.util.InjectionUtils.Provider;
 
/**
* The implementation of the IoC container.
*
* @author sergio.oliveira.jr@gmail.com
*/
public class MentaContainer implements Container {
 
private Map<String, Factory> factoriesByName = new Hashtable<String, Factory>();
private Map<String, Scope> scopes = new Hashtable<String, Scope>();
private Map<String, Object> singletonsCache = new Hashtable<String, Object>();
private Map<String, ThreadLocal<Object>> threadLocalsCache = new Hashtable<String, ThreadLocal<Object>>();
private Set<SetterDependency> setterDependencies = Collections.synchronizedSet(new HashSet<SetterDependency>());
private Set<ConstructorDependency> constructorDependencies = Collections.synchronizedSet(new HashSet<ConstructorDependency>());
private Set<ConstructorDependency> forConstructMethod = Collections.synchronizedSet(new HashSet<ConstructorDependency>());
@Override
public Class<?> getType(Object key) {
String k = InjectionUtils.getKeyName(key);
Factory factory = factoriesByName.get(k);
if (factory == null) return null;
return factory.getType();
}
@Override
public void clear(Scope scope) {
if (scope == Scope.SINGLETON) {
List<ClearableHolder> listToClear = new LinkedList<ClearableHolder>();
synchronized(this) {
for(String key : singletonsCache.keySet()) {
Factory factory = factoriesByName.get(key);
if (factory instanceof Interceptor) {
Interceptor c = (Interceptor) factory;
Object value = singletonsCache.get(key);
listToClear.add(new ClearableHolder(c, value));
}
}
singletonsCache.clear();
}
// clear everything inside a non-synchronized block...
for(ClearableHolder cp : listToClear) cp.clear();
} else if (scope == Scope.THREAD) {
List<ClearableHolder> listToClear = new LinkedList<ClearableHolder>();
synchronized(this) {
for(String key : threadLocalsCache.keySet()) {
Factory factory = factoriesByName.get(key);
if (factory instanceof Interceptor) {
Interceptor c = (Interceptor) factory;
ThreadLocal<Object> t = threadLocalsCache.get(key);
Object value = t.get();
// we are ONLY clearing if this thread has something in the threadlocal, in other words,
// if the thread has previously requested this key...
if (value != null) listToClear.add(new ClearableHolder(c, value));
}
}
 
// and now we clear all thread locals belonging to this thread...
// this will only clear the instances related to this thread...
for(ThreadLocal<Object> t : threadLocalsCache.values()) {
t.remove();
}
}
// clear everything inside a non-synchronized block...
for(ClearableHolder cp : listToClear) cp.clear();
}
}
@Override
public <T> T clear(Object key) {
String keyString = InjectionUtils.getKeyName(key);
if (!factoriesByName.containsKey(keyString)) return null;
Scope scope = scopes.get(keyString);
if (scope == Scope.SINGLETON) {
ClearableHolder cp = null;
Object value = null;
synchronized(this) {
value = singletonsCache.remove(keyString);
if (value != null) {
Factory factory = factoriesByName.get(keyString);
if (factory instanceof Interceptor) {
Interceptor c = (Interceptor) factory;
cp = new ClearableHolder(c, value);
}
}
}
if (cp != null) cp.clear();
return (T) value;
} else if (scope == Scope.THREAD) {
ClearableHolder cp = null;
Object retVal = null;
synchronized(this) {
ThreadLocal<Object> t = threadLocalsCache.get(keyString);
if (t != null) {
Object o = t.get();
if (o != null) {
Factory factory = factoriesByName.get(keyString);
if (factory instanceof Interceptor) {
Interceptor c = (Interceptor) factory;
cp = new ClearableHolder(c, o);
}
t.remove();
retVal = o;
}
}
}
if (cp != null) cp.clear();
return (T) retVal;
} else if (scope == Scope.NONE) {
return null; // always...
} else {
throw new UnsupportedOperationException("Scope not supported: " + scope);
}
}
 
@Override
public <T> T get(Object key) {
String keyString = InjectionUtils.getKeyName(key);
 
if (!factoriesByName.containsKey(keyString)) return null;
 
Factory c = factoriesByName.get(keyString);
Scope scope = scopes.get(keyString);
Object target = null;
 
try {
 
if (scope == Scope.SINGLETON) {
boolean needsToCreate = false;
synchronized(this) {
 
if (singletonsCache.containsKey(keyString)) {
target = singletonsCache.get(keyString);
return (T) target; // no need to wire again...
} else {
needsToCreate = true;
}
}
if (needsToCreate) {
// getInstance needs to be in a non-synchronized block
target = c.getInstance();
checkInterceptable(c, target);
synchronized(this) {
 
singletonsCache.put(keyString, target);
}
}
} else if (scope == Scope.THREAD) {
boolean needsToCreate = false;
boolean needsToAddToCache = false;
ThreadLocal<Object> t = null;
synchronized(this) {
if (threadLocalsCache.containsKey(keyString)) {
t = threadLocalsCache.get(keyString);
target = t.get();
if (target == null) { // different thread...
needsToCreate = true;
// don't return... let it be wired...
} else {
return (T) target; // no need to wire again...
}
} else {
t = new ThreadLocal<Object>();
needsToCreate = true;
needsToAddToCache = true;
// let it be wired...
}
}
if (needsToCreate) {
// getInstance needs to be in a non-synchronized block
target = c.getInstance();
checkInterceptable(c, target);
t.set(target);
}
if (needsToAddToCache) {
synchronized(this) {
threadLocalsCache.put(keyString, t);
}
}
} else if (scope == Scope.NONE) {
 
target = c.getInstance();
checkInterceptable(c, target);
} else {
throw new UnsupportedOperationException("Don't know how to handle scope: " + scope);
}
 
if (target != null) {
 
for (SetterDependency d : setterDependencies) {
 
// has dependency ?
Method m = d.check(target.getClass());
 
if (m != null) {
 
String sourceKey = d.getSource();
 
if (sourceKey.equals(keyString)) {
 
// cannot depend on itself... also avoid recursive StackOverflow...
 
continue;
 
}
 
Object source = get(sourceKey);
 
try {
 
// inject
m.invoke(target, source);
 
} catch (Exception e) {
 
throw new RuntimeException("Cannot inject dependency: method = " + (m != null ? m.getName() : "NULL") + " / source = "
+ (source != null ? source : "NULL") + " / target = " + target, e);
 
}
}
}
}
 
return (T) target; // return target nicely with all the dependencies
 
} catch (Exception e) {
 
throw new RuntimeException(e);
}
}
private final void checkInterceptable(Factory f, Object value) {
if (f instanceof Interceptor) {
Interceptor i = (Interceptor) f;
((Interceptor) f).onCreated(value);
}
}
@Override
public Factory ioc(Object key, Factory factory, Scope scope) {
String keyString = InjectionUtils.getKeyName(key);
factoriesByName.put(keyString, factory);
singletonsCache.remove(keyString); // just in case we are overriding a previous singleton bean...
ThreadLocal<Object> threadLocal = threadLocalsCache.remove(keyString); // just in case we are overriding a previous thread local...
if (threadLocal != null) {
threadLocal.remove();
}
scopes.put(keyString, scope);
forConstructMethod.add(new ConstructorDependency(keyString, factory.getType()));
return factory;
}
@Override
public Factory ioc(Object key, Factory factory) {
return ioc(key, factory, Scope.NONE);
}
@Override
public ConfigurableFactory ioc(Object key, Class<?> klass) {
ConfigurableFactory cc = new ClassFactory(this, klass);
ioc(key, cc);
return cc;
}
@Override
public ConfigurableFactory ioc(Object key, Class<?> klass, Scope scope) {
ConfigurableFactory cc = new ClassFactory(this, klass);
ioc(key, cc, scope);
return cc;
}
@Override
public void autowire(Object sourceFromContainer) {
// autowire by constructor and setter...
String s = InjectionUtils.getKeyName(sourceFromContainer);
autowireBySetter(s);
autowireByConstructor(s);
}
@Override
public void autowire(Object sourceFromContainer, String beanProperty) {
// autowire by constructor and setter...
String s = InjectionUtils.getKeyName(sourceFromContainer);
autowireBySetter(beanProperty, s);
autowireByConstructor(s);
}
 
private void autowireBySetter(String targetProperty, String sourceFromContainer) {
Class<?> sourceType = getType(sourceFromContainer);
 
SetterDependency d = new SetterDependency(targetProperty, sourceFromContainer, sourceType);
setterDependencies.add(d);
}
private void autowireBySetter(String targetProperty) {
autowireBySetter(targetProperty, targetProperty);
}
private void autowireByConstructor(String sourceFromContainer) {
Class<?> sourceType = getType(sourceFromContainer);
ConstructorDependency d = new ConstructorDependency(sourceFromContainer, sourceType);
constructorDependencies.add(d);
}
Set<ConstructorDependency> getConstructorDependencies() {
return constructorDependencies;
}
@Override
public <T> T construct(Class<?> klass) {
ClassFactory f = new ClassFactory(this, klass, forConstructMethod);
return (T) f.getInstance();
}
 
@Override
public void inject(Object bean) {
Provider p = new Provider() {
@Override
public Object get(String key) {
return MentaContainer.this.get(key);
}
@Override
public boolean hasValue(String key) {
return MentaContainer.this.check(key);
}
};
try {
 
InjectionUtils.getObject(bean, p, false, null, true, false, true);
} catch(Exception e) {
throw new RuntimeException("Error populating bean: " + bean, e);
}
}
 
@Override
public synchronized boolean check(Object obj) {
String key = InjectionUtils.getKeyName(obj);
if (!factoriesByName.containsKey(key)) return false;
Scope scope = scopes.get(key);
if (scope == Scope.NONE) {
return false; // always...
} else if (scope == Scope.SINGLETON) {
return singletonsCache.containsKey(key);
} else if (scope == Scope.THREAD) {
ThreadLocal<Object> t = threadLocalsCache.get(key);
if (t != null) return t.get() != null;
return false;
} else {
throw new UnsupportedOperationException("This scope is not supported: " + scope);
}
}
private static class ClearableHolder {
 
private Interceptor c;
private Object value;
public ClearableHolder(Interceptor c, Object value) {
this.c = c;
this.value = value;
}
public void clear() {
c.onCleared(value);
}
}
}
/trunk/src/main/java/org/mentacontainer/impl/SingletonFactory.java
New file
0,0 → 1,30
package org.mentacontainer.impl;
 
import org.mentacontainer.Factory;
 
public class SingletonFactory implements Factory {
private final Object instance;
private final Class<?> type;
public SingletonFactory(Object instance) {
 
this.instance = instance;
this.type = instance.getClass();
}
@Override
public <T> T getInstance() {
return (T) instance;
}
@Override
public Class<?> getType() {
return type;
}
}
/trunk/src/main/java/org/mentacontainer/impl/ClassFactory.java
New file
0,0 → 1,505
package org.mentacontainer.impl;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
import org.mentacontainer.ConfigurableFactory;
import org.mentacontainer.util.FindConstructor;
import org.mentacontainer.util.FindMethod;
import org.mentacontainer.util.InjectionUtils;
 
/**
* The implementation of the Configurable Factory.
*
* @author sergio.oliveira.jr@gmail.com
*/
class ClassFactory implements ConfigurableFactory {
private final MentaContainer container;
private final Class<?> klass;
private Map<String, Object> props = null;
private List<Object> initValues = null;
private List<Class<?>> initTypes = null;
private Constructor<?> constructor = null;
private Map<String, Method> cache = null;
private boolean useZeroArgumentsConstructor = false;
private final Set<ConstructorDependency> constructorDependencies;
public ClassFactory(MentaContainer container, Class<?> klass) {
 
this(container, klass, null);
}
ClassFactory(MentaContainer container, Class<?> klass, Set<ConstructorDependency> constructorDependencies) {
this.container = container;
this.klass = klass;
this.constructorDependencies = constructorDependencies;
}
 
@Override
public ConfigurableFactory addPropertyValue(String name, Object value) {
if (props == null) {
props = new HashMap<String, Object>();
cache = new HashMap<String, Method>();
}
props.put(name, value);
return this;
}
@Override
public ConfigurableFactory useZeroArgumentConstructor() {
this.useZeroArgumentsConstructor = true;
return this;
}
@Override
public ConfigurableFactory addPropertyDependency(String property, Object key) {
String k = InjectionUtils.getKeyName(key);
return addPropertyValue(property, new DependencyKey(k));
}
@Override
public ConfigurableFactory addPropertyDependency(String property) {
return addPropertyDependency(property, property);
}
@Override
public ConfigurableFactory addConstructorDependency(Object key) {
String k = InjectionUtils.getKeyName(key);
return addInitValue(new DependencyKey(k), container.getType(k));
}
private ConfigurableFactory addInitValue(Object value, Class<?> type) {
if (initValues == null) {
initValues = new LinkedList<Object>();
initTypes = new LinkedList<Class<?>>();
}
initValues.add(value);
initTypes.add(type);
return this;
}
@Override
public ConfigurableFactory addInitValue(Object value) {
return addInitValue(value, value.getClass());
}
@Override
public ConfigurableFactory addInitPrimitive(Object value) {
Class<?> primitive = getPrimitiveFrom(value);
if (primitive == null) throw new IllegalArgumentException("Value is not a primitive: " + value);
return addInitValue(value, primitive);
}
private List<Class<?>> convertToPrimitives(List<Class<?>> list) {
if (list == null) return null;
Iterator<Class<?>> iter = list.iterator();
List<Class<?>> results = new LinkedList<Class<?>>();
while(iter.hasNext()) {
Class<?> klass = iter.next();
Class<?> primitive = getPrimitiveFrom(klass);
if (primitive != null) {
results.add(primitive);
} else {
results.add(klass);
}
}
return results;
}
private Class<?>[] getClasses(List<Class<?>> values) {
if (values == null) return new Class[0];
Class<?>[] types = (Class<?>[]) new Class[values.size()];
return values.toArray(types);
}
private Object [] getValues(List<Object> values) throws InstantiationException {
if (values == null) return null;
Object [] array = new Object[values.size()];
int index = 0;
Iterator<Object> iter = values.iterator();
while(iter.hasNext()) {
Object obj = iter.next();
if (obj instanceof DependencyKey) {
DependencyKey dk = (DependencyKey) obj;
array[index++] = container.get(dk.getKey());
} else {
array[index++] = obj;
}
}
return array;
}
/*
* Use reflection to set a property in the bean
*/
private void setValue(Object bean, String name, Object value) {
try {
StringBuffer sb = new StringBuffer(30);
sb.append("set");
sb.append(name.substring(0,1).toUpperCase());
if (name.length() > 1) sb.append(name.substring(1));
String methodName = sb.toString();
if (!cache.containsKey(name)) {
Method m = null;
try {
m = FindMethod.getMethod(klass, methodName, new Class[] { value.getClass() });
} catch(Exception e) {
// try primitive...
Class<?> primitive = getPrimitiveFrom(value);
if (primitive != null) {
try {
m = klass.getMethod(methodName, new Class[] { primitive });
} catch(Exception ex) {
// not found!
}
}
if (m == null) {
throw new InstantiationException("Cannot find method for property: " + name);
}
}
if (m != null) {
cache.put(name, m);
m.setAccessible(true);
}
}
 
Method m = cache.get(name);
if (m != null) {
m.invoke(bean, new Object[] { value });
}
} catch(Exception e) {
throw new RuntimeException("Error trying to set a property with reflection: " + name, e);
}
}
private static Class<?> getPrimitiveFrom(Object w) {
if (w instanceof Boolean) { return Boolean.TYPE; }
else if (w instanceof Byte) { return Byte.TYPE; }
else if (w instanceof Short) { return Short.TYPE; }
else if (w instanceof Character) { return Character.TYPE; }
else if (w instanceof Integer) { return Integer.TYPE; }
else if (w instanceof Long) { return Long.TYPE; }
else if (w instanceof Float) { return Float.TYPE; }
else if (w instanceof Double) { return Double.TYPE; }
return null;
}
private static Class<?> getPrimitiveFrom(Class<?> klass) {
if (klass.equals(Boolean.class)) { return Boolean.TYPE; }
else if (klass.equals(Byte.class)) { return Byte.TYPE; }
else if (klass.equals(Short.class)) { return Short.TYPE; }
else if (klass.equals(Character.class)) { return Character.TYPE; }
else if (klass.equals(Integer.class)) { return Integer.TYPE; }
else if (klass.equals(Long.class)) { return Long.TYPE; }
else if (klass.equals(Float.class)) { return Float.TYPE; }
else if (klass.equals(Double.class)) { return Double.TYPE; }
return null;
}
@Override
public <T> T getInstance() {
Object obj = null;
Object[] values = null;
synchronized(this) {
if (constructor == null) {
if (!useZeroArgumentsConstructor) {
checkConstructorDependencies();
} else {
if (initTypes != null) initTypes = null; // just in case client did something stupid...
if (initValues != null) initValues = null; // just in case client did something stupid...
}
try {
//constructor = klass.getConstructor(getClasses(initTypes));
constructor = FindConstructor.getConstructor(klass, getClasses(initTypes));
} catch(Exception e) {
// try primitives...
try {
//constructor = klass.getConstructor(getClasses(convertToPrimitives(initTypes)));
constructor = FindConstructor.getConstructor(klass, getClasses(convertToPrimitives(initTypes)));
} catch(Exception ee) {
throw new RuntimeException("Cannot find a constructor for class: " + klass);
}
}
}
try {
values = getValues(initValues);
} catch(Exception e) {
new RuntimeException("Cannot instantiate values for constructor!", e);
}
}
try {
obj = constructor.newInstance(values);
} catch(Exception e) {
throw new RuntimeException("Cannot create instance from constructor: " + constructor, e);
}
if (props != null && props.size() > 0) {
Iterator<String> iter = props.keySet().iterator();
while(iter.hasNext()) {
String name = iter.next();
Object value = props.get(name);
if (value instanceof DependencyKey) {
DependencyKey dk = (DependencyKey) value;
value = container.get(dk.getKey());
}
setValue(obj, name, value);
}
}
return (T) obj;
}
private static boolean betterIsAssignableFrom(Class<?> klass1, Class<?> klass2) {
// with autoboxing both ways...
if (klass1.isAssignableFrom(klass2)) return true;
Class<?> k1 = klass1.isPrimitive() ? klass1 : getPrimitiveFrom(klass1);
Class<?> k2 = klass2.isPrimitive() ? klass2 : getPrimitiveFrom(klass2);
if (k1 == null || k2 == null) return false;
return k1.isAssignableFrom(k2);
}
private void checkConstructorDependencies() {
Constructor<?>[] constructors = klass.getConstructors();
for(Constructor<?> c : constructors) {
LinkedList<Class<?>> providedInitTypes = null;
if (initTypes != null) {
providedInitTypes = new LinkedList<Class<?>>(initTypes);
} else {
providedInitTypes = new LinkedList<Class<?>>();
}
LinkedList<Object> providedInitValues = null;
if (initValues != null) {
providedInitValues = new LinkedList<Object>(initValues);
} else {
providedInitValues = new LinkedList<Object>();
}
LinkedList<Class<?>> newInitTypes = new LinkedList<Class<?>>();
LinkedList<Object> newInitValues = new LinkedList<Object>();
Set<ConstructorDependency> constructorDependencies = this.constructorDependencies != null ? this.constructorDependencies : container.getConstructorDependencies();
Set<ConstructorDependency> dependencies = new HashSet<ConstructorDependency>(constructorDependencies);
Class<?>[] constructorParams = c.getParameterTypes();
if (constructorParams == null || constructorParams.length == 0) continue; // skip default constructor for now...
for(Class<?> constructorParam : constructorParams) {
// first see if it was provided...
Class<?> provided = providedInitTypes.isEmpty() ? null : providedInitTypes.get(0);
if (provided != null && constructorParam.isAssignableFrom(provided)) {
newInitTypes.add(providedInitTypes.removeFirst()); // we matched this one, so remove...
newInitValues.add(providedInitValues.removeFirst());
continue;
} else {
// check auto-wiring...
Iterator<ConstructorDependency> iter = dependencies.iterator();
boolean foundMatch = false;
while(iter.hasNext()) {
ConstructorDependency d = iter.next();
if (betterIsAssignableFrom(constructorParam, d.getSourceType())) {
iter.remove();
newInitTypes.add(d.getSourceType());
newInitValues.add(new DependencyKey(d.getSource()));
foundMatch = true;
break;
}
}
if (foundMatch) {
continue; // next constructor param...
}
}
break; // no param... next constructor...
}
// done, check if found...
if (constructorParams.length == newInitTypes.size() && providedInitTypes.isEmpty()) {
this.initTypes = newInitTypes;
this.initValues = newInitValues;
}
}
}
private static class DependencyKey {
private String key;
public DependencyKey(String key) { this.key = key; }
private String getKey() { return key; }
}
@Override
public Class<?> getType() {
return klass;
}
}
/trunk/src/main/java/org/mentacontainer/Container.java
New file
0,0 → 1,156
package org.mentacontainer;
 
 
/**
* A IoC container that provides:
* <ul>
* <li>Programmatic Configuration</li>
* <li>Bean Instantiation through constructors</li>
* <li>Bean Initialization through setters</li>
* <li>Dependency Injection through constructors</li>
* <li>Dependency Injection through setters</li>
* <li>Auto-wiring through constructors and setters (very simple!)</li>
* <li>Injection through setters so you can populate any external object with objects from the container</li>
* <li>Instantiation through constructors so you can instantiate any external class with objects from the container</li>
* <li>Support for SINGLETON and THREAD scopes, plus you can easily create REQUEST and SESSION scopes for web projects</li>
* <li>Generic Factories so you can easily turn anything into a object factory</li>
* <li>Interceptors for factories: onCreated, onCleared, useful for object pooling</li>
* </ul>
*
* @author sergio.oliveira.jr@gmail.com
*
*/
public interface Container {
/**
* Get an instance from the container by using the associated factory.
*
* The instance will be fully initialized (through constructor and/or setters) and fully wired (all dependencies will be resolved).
*
* @param key The key representing the factory to use. The name of the bean in the container.
* @return The fully initialized and wired bean.
*/
public <T> T get(Object key);
/**
* Get the type of the instances returned by the associated factory.
*
* @param key The factory
* @return The type returned by this factory
*/
public Class<?> getType(Object key);
/**
* Configure a bean to be returned with the given implementation when {@link #get(String)} is called.
* An internal factory will be used.
*
* @param key The key representing the bean to return. The name of the bean in the container.
* @param klass The class used to instantiate the bean, in other words, its implementation.
* @param scope The scope of the factory.
* @return The factory created as a ConfigurableFactory. (Fluent API)
* @see Scope
*/
public ConfigurableFactory ioc(Object key, Class<?> klass, Scope scope);
/**
* Same as {@link #ioc(String, Class, Scope)} except that it assumes
* there is no scope (Scope.NONE).
*
* @param key
* @param klass
* @return The factory created as a ConfigurableFactory. (Fluent API)
* @see Scope
*/
public ConfigurableFactory ioc(Object key, Class<?extends Object> klass);
/**
* Set up a factory for the given key. The scope assumed is NONE.
*
* @param key The key representing the bean to return. The name of the bean in the container.
* @param factory The factory for the IoC.
* @return The factory passed as a parameter. (Fluent API)
* @see Factory
*/
public Factory ioc(Object key, Factory factory);
/**
* Set up a factory for the given key in the given scope.
*
* @param key The key representing the bean to return. The name of the bean in the container.
* @param factory The factory for the IoC.
* @param scope The scope used by the factory.
* @return The factory passed as a parameter (Fluent API).
* @see Factory
* @see Scope
*/
public Factory ioc(Object key, Factory factory, Scope scope);
/**
* Configure a bean dependency to be auto-wired by the container.
* It wires by constructor and by setter. By constructor is uses the type of sourceFromContainer. By setter it assumes the property is also named sourceFromContainer.
*
* @param sourceFromContainer The bean inside the container that will be wired automatically inside any other bean the depends on it.
*/
public void autowire(Object sourceFromContainer);
/**
* Configure a bean dependency to be auto-wired by the container.
* It wires by constructor and by setter. By constructor is uses the type of sourceFromContainer. By setter it looks for a property with the given name and try to inject.
*
* @param sourceFromContainer The bean inside the container that will be wired automatically inside any other bean the depends on it.
* @param property The name of the property to inject, whey trying auto-wiring by setter.
*/
public void autowire(Object sourceFromContainer, String property);
/**
* Take a given bean and populate its properties with other beans coming from this container.
* You basically checking properties of the given bean and looking for values inside the container.
* And injecting in the given bean, in other words, populating it.
*
* @param bean The bean to be populated with other beans from the container.
*/
public void inject(Object bean);
/**
* Construct an instance using beans from the container. A constructor will be chosen that has arguments that can be found
* inside the container.
*
* @param klass The class that should be instantiated.
* @return An instantiated bean.
*/
public <T> T construct(Class<?> klass);
/**
* Check whether the container currently has a value for this key. For example,
* if it is a singleton AND someone has requested it, the container will have it cached.
* The method is useful to check for an instance without forcing her creation.
*
* @param key The key representing the bean inside the container.
* @return true if the container has an instance cached in the scope for this key
*/
public boolean check(Object key);
/**
* Clear all cached instances for that scope. If you have a thread-pool for example you will
* want to clear the THREAD scope when your thread is returned to the pool. Because you have a thread
* pool you will have the SAME thread handling different requests and each request will need its own instances
* from the container. Therefore, each time you are done with a thread and it is returned to your thread-pool
* you can call clear to release the instances allocated and cached by the container. A web container and/or framework
* can use this feature to implement a REQUEST scope which is nothing more than the THREAD scope with clear. If the web
* container was not using a thread-pool, the THREAD scope would be equal to the REQUEST scope as each request would
* always be handled by a different thread.
*
* It does not make sense to clear a NONE scope (the method returns doing nothing). You can clear a SINGLETON scope if necessary.
*
* @param scope The scope to be cleared.
*/
public void clear(Scope scope);
/**
* Clear a single key from cache and return the instance that was cached.
*
* @param key The key representing the bean inside the container.
* @return The value that was cached and it is not anymore (was cleared) or null if nothing was cleared
*/
public <T> T clear(Object key);
}
/trunk/src/main/java/org/mentacontainer/Factory.java
New file
0,0 → 1,24
package org.mentacontainer;
 
/**
* An IoC factory that knows how to create instances.
*
* @author sergio.oliveira.jr@gmail.com
*/
public interface Factory {
/**
* Returns an instance. Creates one if necessary.
*
* @return an instance
*/
public <T> T getInstance();
/**
* Return the type of objects that this factory disposes.
*
* @return the type of objects returned by this factory.
*/
public Class<?> getType();
}
/trunk/src/main/java/org/mentacontainer/ConfigurableFactory.java
New file
0,0 → 1,89
package org.mentacontainer;
 
/**
* An IoC factory that knows how to create instances and
* can be configured by accepting values for its constructor
* and properties (setters). It can also be intercepted right
* after it creates an instance and right before it releases an instance
* through the Interceptor interface.
*
* It also supports constructor and property values that are dependencies, in other words, they come from the container itself.
*
* @author sergio.oliveira.jr@gmail.com
* @see Interceptor
*/
public interface ConfigurableFactory extends Factory {
/**
* Add a constructor parameter to be used when the bean is instantiated. It can be called more than once to
* use constructors with more than one argument.
*
* @param value A parameter value to be used by a constructor.
* @return The factory itself. (Fluent API)
*/
public ConfigurableFactory addInitValue(Object value);
/**
* Add a constructor parameter that is a primitive to be used when the bean is instantiated. It can be called more than once to
* use constructors with more than one argument.<br/>
* <br/>
* Note: This method is seldom necessary and should be used if and only if you have a constructor that mixes Wrappers and primitives, like below:<br/>
* <br/><pre>
* public AObject(int x, Integer i, Boolean b, boolean f) { ... }
* </pre>
*
* @param value A parameter value to be used by a constructor. Must be a primitive that will be autoboxed.
* @return The factory itself. (Fluent API)
*/
public ConfigurableFactory addInitPrimitive(Object value);
/**
* Add a constructor parameter that is a dependency, in other words, it gets its value from the container.
* When the object is created the dependency will be obtained from the container.
*
* @param key The key used to get an instance from the container
* @return The factory itself. (Fluent API)
*/
public ConfigurableFactory addConstructorDependency(Object key);
/**
* In case you want to force the use of a zero argument constructor and avoid any ambiguity when choosing the constructor to use.
*
* This method is seldom necessary and should be used in the rare cases that the container cannot correctly determine the constructor you
* want to use due to auto-wiring.
*
* @return The factory itself. (Fluent API)
*/
public ConfigurableFactory useZeroArgumentConstructor();
/**
* Add a property to be injected through a setter when the factory instantiates an object.
*
* @param name The property name.
* @param value The property value.
* @return The factory itself. (Fluent API)
*/
public ConfigurableFactory addPropertyValue(String name, Object value);
/**
* Add a setter property that is a dependency, in other words, its value will be obtained from the container.
*
* The property name and the dependency name are the same. If they are different you can use the other version of addPropertyDependency that accepts both values.
*
* @param property The dependency name which is equal to the property name.
* @return The factory itself. (Fluent API)
*/
public ConfigurableFactory addPropertyDependency(String property);
/**
* Add a setter property that is a dependency, in other words, its value will be obtained from the container.
*
* The property name and the dependency name are different.
*
* @param property The property that will be injected by the container.
* @param key The dependency name, in other words, the key used to get a bean from the container.
* @return The factory itself. (Fluent API)
*/
public ConfigurableFactory addPropertyDependency(String property, Object key);
}
/trunk/src/main/java/org/mentacontainer/Scope.java
New file
0,0 → 1,19
package org.mentacontainer;
 
public enum Scope {
/**
* The container calls factory.getInstance on every request for the bean, returning always new instances.
*/
NONE,
/**
* The container calls factory.getInstance only once and caches the value, returning always the same instance.
*/
SINGLETON,
/**
* The container calls factory.getInstance and caches the value on a thread local, so the same thread will always get the same instance, at least until the scope is cleared by the client.
*/
THREAD
}
/trunk/src/main/java/org/mentacontainer/example/BasicOperations.java
New file
0,0 → 1,274
package org.mentacontainer.example;
 
import java.util.Date;
 
import org.mentacontainer.Container;
import org.mentacontainer.Scope;
import org.mentacontainer.impl.MentaContainer;
 
public class BasicOperations {
 
public static void main(String[] args) {
 
case1();
case2();
case3();
case4();
case5();
case6();
case7();
case8();
case9();
case10();
}
 
public static class Connection {
 
}
 
public static interface UserDAO {
 
public String getUsername(int id);
}
 
public static class JdbcUserDAO implements UserDAO {
 
private Connection conn;
 
public void setConnection(Connection conn) {
this.conn = conn;
}
 
@Override
public String getUsername(int id) {
 
// connection will be injected by the container...
if (conn == null) throw new IllegalStateException("conn is null!");
 
// use the connection to get the username...
 
return "saoj";
}
}
 
public static interface AccountDAO {
 
public double getBalance(int id);
}
 
public static class JdbcAccountDAO implements AccountDAO {
 
private final Connection conn;
 
public JdbcAccountDAO(Connection conn) {
this.conn = conn;
}
 
@Override
public double getBalance(int id) {
 
assert conn != null;
 
// use the connection to get the balance...
return 1000000D;
}
}
private static void case9() {
Container c = new MentaContainer();
 
c.ioc("connection", Connection.class); // in real life this will be a connection pool factory...
c.ioc("accountDAO", JdbcAccountDAO.class);
c.ioc("userDAO", JdbcUserDAO.class);
 
c.autowire("connection"); // all beans that need a connection in the constructor or setter will receive one...
 
AccountDAO accountDAO = c.get("accountDAO");
UserDAO userDAO = c.get("userDAO");
 
System.out.println(accountDAO.getBalance(25)); // => 1000000
System.out.println(userDAO.getUsername(45)); // => "saoj"
}
 
private static void case1() {
 
Container c = new MentaContainer();
 
c.ioc("myString1", String.class);
 
String myString1 = c.get("myString1");
 
System.out.println(myString1); // ==> "" ==> default constructor new String() was used
 
c.ioc("myString2", String.class).addInitValue("saoj");
 
String myString2 = c.get("myString2");
 
System.out.println(myString2); // ==> "saoj" ==> constructor new String("saoj") was used
 
c.ioc("myDate1", Date.class).addPropertyValue("hours", 15) // setHours(15)
.addPropertyValue("minutes", 10) // setMinutes(10)
.addPropertyValue("seconds", 45); // setSeconds(45)
 
Date myDate1 = c.get("myDate1");
 
System.out.println(myDate1); // ==> a date with time 15:10:45
}
 
private static void case5() {
 
Container c = new MentaContainer();
 
c.ioc("connection", Connection.class); // in real life this will be a connection pool factory...
 
c.ioc("accountDAO", JdbcAccountDAO.class).addConstructorDependency("connection");
 
AccountDAO accountDAO = c.get("accountDAO");
 
System.out.println(accountDAO.getBalance(25)); // => 1000000
}
 
private static void case7() {
 
Container c = new MentaContainer();
 
c.ioc("connection", Connection.class); // in real life this will be a connection pool factory...
 
c.ioc("accountDAO", JdbcAccountDAO.class);
 
c.autowire("connection"); // all beans that need a connection in the constructor will get one...
 
AccountDAO accountDAO = c.get("accountDAO");
 
System.out.println(accountDAO.getBalance(25)); // => 1000000
 
}
 
private static void case6() {
 
Container c = new MentaContainer();
 
c.ioc("connection", Connection.class); // in real life this will be a connection pool factory...
 
c.ioc("userDAO", JdbcUserDAO.class).addPropertyDependency("connection");
 
UserDAO userDAO = c.get("userDAO");
 
System.out.println(userDAO.getUsername(54)); // => "saoj"
}
 
private static void case8() {
 
Container c = new MentaContainer();
 
c.ioc("connection", Connection.class); // in real life this will be a connection pool factory...
 
c.ioc("userDAO", JdbcUserDAO.class);
 
c.autowire("connection");
 
UserDAO userDAO = c.get("userDAO");
 
System.out.println(userDAO.getUsername(54)); // => "saoj"
 
}
 
private static void case2() {
 
Container c = new MentaContainer();
 
c.ioc("myString", String.class, Scope.SINGLETON).addInitValue("saoj");
 
String s1 = c.get("myString");
 
String s2 = c.get("myString");
 
System.out.println(s1 == s2); // ==> true ==> same instance
 
System.out.println(s1.equals(s2)); // ==> true => of course
}
 
private static void case3() {
 
Container c = new MentaContainer();
 
c.ioc("userDAO", JdbcUserDAO.class);
 
c.ioc("connection", Connection.class); // in real life this would be a connection pool
// or the hibernate SessionFactory
 
// "conn" = the name of the property
// Connection.class = the type of the property
// "connection" = the source from where the dependency will come from
c.autowire("connection");
 
UserDAO userDAO = c.get("userDAO");
 
// the container detects that userDAO has a dependency: name = "conn" and type = "Connection.class"
// where does it go to get the dependency to insert?
// In itself: it does a Container.get("connection") => "connection" => the source
 
System.out.println(userDAO.getUsername(11)); // ==> "saoj" ==> connection is not null as expected...
}
 
public static class SomeService {
 
private UserDAO userDAO;
 
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
 
public void doSomething() {
System.out.println(userDAO.getUsername(11));
}
}
 
private static void case4() {
 
Container c = new MentaContainer();
 
c.ioc("userDAO", JdbcUserDAO.class);
 
c.ioc("connection", Connection.class);
 
c.autowire("connection");
 
SomeService service = new SomeService();
 
c.inject(service); // populate (inject) all properties of SomeService with
// beans from the container
 
service.doSomething(); // ==> "saoj"
}
public static class SomeService2 {
 
private final UserDAO userDAO;
 
public SomeService2(UserDAO userDAO) {
this.userDAO = userDAO;
}
public void doSomething() {
System.out.println(userDAO.getUsername(11));
}
}
 
private static void case10() {
 
Container c = new MentaContainer();
 
c.ioc("userDAO", JdbcUserDAO.class);
 
c.ioc("connection", Connection.class);
 
c.autowire("connection");
SomeService2 service = c.construct(SomeService2.class);
 
service.doSomething(); // ==> "saoj"
}
 
}
/trunk/src/main/java/org/mentacontainer/util/FindMethod.java
New file
0,0 → 1,144
package org.mentacontainer.util;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
 
/**
* Find method with polymorphism!
* Class.getMethod only finds an exact match.
*
* @author Jon Skeet (http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/921ab91865c8cc2e/9e141d3d62e7cb3f)
*/
public class FindMethod {
 
/**
* Finds the most specific applicable method
*
* @param source Class to find method in
* @param name Name of method to find
* @param parameterTypes Parameter types to search for
*/
public static Method getMethod(Class<?> source,
String name,
Class<?>[] parameterTypes)
throws NoSuchMethodException {
return internalFind(source.getMethods(),
name,
parameterTypes);
}
 
/**
* Finds the most specific applicable declared method
*
* @param source Class to find method in
* @param name Name of method to find
* @param parameterTypes Parameter types to search for
*/
public static Method getDeclaredMethod(Class<?> source,
String name,
Class<?>[] parameterTypes)
throws NoSuchMethodException {
return internalFind(source.getDeclaredMethods(),
name,
parameterTypes);
}
 
/**
* Internal method to find the most specific applicable method
*/
private static Method internalFind(Method[] toTest,
String name,
Class<?>[] parameterTypes)
throws NoSuchMethodException {
int l = parameterTypes.length;
 
// First find the applicable methods
List<Method> applicableMethods = new LinkedList<Method>();
 
for (int i = 0; i < toTest.length; i++) {
// Check the name matches
if (!toTest[i].getName().equals(name))
continue;
// Check the parameters match
Class<?>[] params = toTest[i].getParameterTypes();
 
if (params.length != l)
continue;
int j;
 
for (j = 0; j < l; j++)
if (!params[j].isAssignableFrom(parameterTypes[j]))
break;
// If so, add it to the list
if (j == l)
applicableMethods.add(toTest[i]);
}
 
/*
* If we've got one or zero methods, we can finish
* the job now.
*/
int size = applicableMethods.size();
 
if (size == 0)
throw new NoSuchMethodException ("No such method: " + name);
if (size == 1)
return applicableMethods.get(0);
 
/*
* Now find the most specific method. Do this in a very primitive
* way - check whether each method is maximally specific. If more
* than one method is maximally specific, we'll throw an exception.
* For a definition of maximally specific, see JLS section 15.11.2.2.
*
* I'm sure there are much quicker ways - and I could probably
* set the second loop to be from i+1 to size. I'd rather not though,
* until I'm sure...
*/
int maximallySpecific = -1; // Index of maximally specific method
 
for (int i = 0; i < size; i++) {
int j;
// In terms of the JLS, current is T
Method current = applicableMethods.get(i);
Class<?>[] currentParams = current.getParameterTypes();
Class<?> currentDeclarer = current.getDeclaringClass();
 
for (j = 0; j < size; j++) {
if (i == j)
continue;
// In terms of the JLS, test is U
Method test = applicableMethods.get(j);
Class<?>[] testParams = test.getParameterTypes();
Class<?> testDeclarer = test.getDeclaringClass();
 
// Check if T is a subclass of U, breaking if not
if (!testDeclarer.isAssignableFrom(currentDeclarer))
break;
 
// Check if each parameter in T is a subclass of the
// equivalent parameter in U
int k;
 
for (k = 0; k < l; k++)
if (!testParams[k].isAssignableFrom(currentParams[k]))
break;
if (k != l)
break;
}
// Maximally specific!
if (j == size) {
if (maximallySpecific != -1)
throw new NoSuchMethodException
("Ambiguous method search - more " +
"than one maximally specific method");
maximallySpecific = i;
}
}
if (maximallySpecific == -1)
throw new NoSuchMethodException ("No maximally specific method.");
return applicableMethods.get(maximallySpecific);
}
 
}
/trunk/src/main/java/org/mentacontainer/util/InjectionUtils.java
New file
0,0 → 1,814
package org.mentacontainer.util;
 
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
 
public class InjectionUtils {
 
/**
* The character used to separate the prefix from the value name when you are using the getObject method with a prefix. You can change the value of this prefix if you want to
* by changing this static variable.
*
* Ex: getObject(User.class, "user") will get all values that begin with "user.".
*/
public static char PREFIX_SEPARATOR = '.';
 
private static Map<Class<?>, Map<String, Object>> settersMaps = new HashMap<Class<?>, Map<String, Object>>();
 
private static Map<Class<?>, Map<String, Object>> fieldsMaps = new HashMap<Class<?>, Map<String, Object>>();
 
public static void prepareForInjection(Class<?> klass, Map<String, Object> setters, Map<String, Object> fields) {
 
StringBuffer sb = new StringBuffer(32);
 
Method[] methods = klass.getMethods();
 
for (int i = 0; i < methods.length; i++) {
 
Method m = methods[i];
 
String name = m.getName();
 
Class<?>[] types = m.getParameterTypes();
 
if (name.startsWith("set") && name.length() > 3 && types.length == 1) {
 
String var = name.substring(3);
 
if (var.length() > 1) {
 
sb.delete(0, sb.length());
 
sb.append(var.substring(0, 1).toLowerCase());
 
sb.append(var.substring(1));
 
var = sb.toString();
 
} else {
 
var = var.toLowerCase();
}
 
m.setAccessible(true);
 
if (setters.containsKey(var)) {
 
Object obj = setters.get(var);
 
if (obj instanceof List) {
 
List<Method> list = (List<Method>) obj;
 
list.add(m);
 
} else if (obj instanceof Method) {
 
List<Method> list = new ArrayList<Method>();
 
list.add((Method) obj);
 
list.add(m);
 
setters.put(var, list);
 
}
 
} else {
 
setters.put(var, m);
 
}
}
}
 
if (fields == null) return;
 
Field[] f = klass.getDeclaredFields();
 
for (int i = 0; i < f.length; i++) {
 
Field field = f[i];
 
field.setAccessible(true);
 
String name = field.getName();
 
if (setters.containsKey(name)) {
 
Object obj = setters.get(name);
 
if (obj instanceof Method) {
 
Method m = (Method) obj;
 
Class<?>[] types = m.getParameterTypes();
 
Class<?> type = field.getType();
 
if (type.isAssignableFrom(types[0])) continue;
 
} else if (obj instanceof List) {
 
List<Method> list = (List<Method>) obj;
 
Iterator<Method> iter = list.iterator();
 
boolean found = false;
 
while (iter.hasNext()) {
 
Method m = iter.next();
 
Class<?>[] types = m.getParameterTypes();
 
Class<?> type = field.getType();
 
if (type.isAssignableFrom(types[0])) {
 
found = true;
 
break;
}
}
 
if (found) continue;
}
}
 
fields.put(name, field);
 
}
}
 
public static boolean checkPrimitives(Class<?> target, Class<?> source) {
 
if (target.equals(int.class) && source.equals(Integer.class)) return true;
 
if (target.equals(boolean.class) && source.equals(Boolean.class)) return true;
 
if (target.equals(byte.class) && source.equals(Byte.class)) return true;
 
if (target.equals(short.class) && source.equals(Short.class)) return true;
 
if (target.equals(char.class) && source.equals(Character.class)) return true;
 
if (target.equals(long.class) && source.equals(Long.class)) return true;
 
if (target.equals(float.class) && source.equals(Float.class)) return true;
 
if (target.equals(double.class) && source.equals(Double.class)) return true;
 
return false;
 
}
 
public static Object tryToConvert(Object source, Class<?> targetType) {
 
return tryToConvert(source, targetType, false);
}
 
public static Object tryToConvert(Object source, Class<?> targetType, boolean tryNumber) {
 
String value = null;
 
if (source instanceof String) {
 
value = (String) source;
 
} else if (tryNumber && source instanceof Number) {
 
value = source.toString();
 
} else {
 
return null;
}
 
Object newValue = null;
 
String className = targetType.getName();
 
if (className.equals("int") || className.equals("java.lang.Integer")) {
int x = -1;
try {
x = Integer.parseInt(value);
} catch (Exception e) {
return null;
}
newValue = new Integer(x);
} else if (className.equals("short") || className.equals("java.lang.Short")) {
short x = -1;
try {
x = Short.parseShort(value);
} catch (Exception e) {
return null;
}
newValue = new Short(x);
 
} else if (className.equals("char") || className.equals("java.lang.Character")) {
 
if (value.length() != 1) {
return null;
}
 
newValue = new Character(value.charAt(0));
 
} else if (className.equals("long") || className.equals("java.lang.Long")) {
long x = -1;
try {
x = Long.parseLong(value);
} catch (Exception e) {
return null;
}
newValue = new Long(x);
} else if (className.equals("float") || className.equals("java.lang.Float")) {
float x = -1;
try {
x = Float.parseFloat(value);
} catch (Exception e) {
return null;
}
newValue = new Float(x);
} else if (className.equals("double") || className.equals("java.lang.Double")) {
double x = -1;
try {
x = Double.parseDouble(value);
} catch (Exception e) {
return null;
}
newValue = new Double(x);
} else if (className.equals("boolean") || className.equals("java.lang.Boolean")) {
try {
int x = Integer.parseInt(value);
if (x == 1) {
newValue = Boolean.TRUE;
} else if (x == 0) {
newValue = Boolean.FALSE;
} else {
return null;
}
} catch (Exception e) {
if (value.equalsIgnoreCase("true") || value.equals("on")) {
newValue = Boolean.TRUE;
} else if (value.equalsIgnoreCase("false")) {
newValue = Boolean.FALSE;
} else {
return null;
}
}
} else if (targetType.isEnum()) {
 
try {
Class k = (Class) targetType; // not sure how to avoid this raw type!
 
newValue = Enum.valueOf(k, value);
 
} catch (Exception e) {
 
return null;
}
 
}
 
return newValue;
 
}
 
public static Object shouldConvertToNull(Object value, Class<?> targetType) {
 
if (targetType.equals(String.class)) {
 
return value;
 
} else if (targetType.isPrimitive()) {
 
return value;
}
 
return null;
}
 
public static Class<?> getPrimitiveFrom(Object w) {
if (w instanceof Boolean) {
return Boolean.TYPE;
} else if (w instanceof Byte) {
return Byte.TYPE;
} else if (w instanceof Short) {
return Short.TYPE;
} else if (w instanceof Character) {
return Character.TYPE;
} else if (w instanceof Integer) {
return Integer.TYPE;
} else if (w instanceof Long) {
return Long.TYPE;
} else if (w instanceof Float) {
return Float.TYPE;
} else if (w instanceof Double) {
return Double.TYPE;
}
return null;
}
 
public static Class<?> getPrimitiveFrom(Class<?> klass) {
 
String s = klass.getName();
 
if (s.equals("java.lang.Boolean")) {
return Boolean.TYPE;
} else if (s.equals("java.lang.Byte")) {
return Byte.TYPE;
} else if (s.equals("java.lang.Short")) {
return Short.TYPE;
} else if (s.equals("java.lang.Character")) {
return Character.TYPE;
} else if (s.equals("java.lang.Integer")) {
return Integer.TYPE;
} else if (s.equals("java.lang.Long")) {
return Long.TYPE;
} else if (s.equals("java.lang.Float")) {
return Float.TYPE;
} else if (s.equals("java.lang.Double")) {
return Double.TYPE;
}
return null;
}
 
public static Field getField(Object target, String name) {
return getField(target.getClass(), name);
}
 
public static Field getField(Class<?> target, String name) {
Field fields[] = target.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
if (name.equals(fields[i].getName())) {
return fields[i];
}
}
return null;
}
public static String getKeyName(Object obj) {
if (obj instanceof Class<?>) {
Class<?> k = (Class<?>) obj;
return k.getName();
}
return obj.toString();
}
 
public static Method findMethodToGet(Class<?> target, String name) {
 
StringBuffer sb = new StringBuffer(128);
 
sb.append("get").append(name.substring(0, 1).toUpperCase());
 
if (name.length() > 1) sb.append(name.substring(1));
 
try {
 
return target.getMethod(sb.toString(), (Class[]) null);
 
} catch (Exception e) {
 
}
 
sb.setLength(0);
 
sb.append("is").append(name.substring(0, 1).toUpperCase());
 
if (name.length() > 1) {
 
sb.append(name.substring(1));
}
 
try {
 
return target.getMethod(sb.toString(), (Class[]) null);
 
} catch (Exception e) {
 
}
 
return null;
}
 
public static Method findMethodToInject(Class<?> target, String name, Class<?> source) {
 
StringBuffer sb = new StringBuffer(128);
 
sb.append("set").append(name.substring(0, 1).toUpperCase());
 
if (name.length() > 1) sb.append(name.substring(1));
 
String methodName = sb.toString();
 
Method m = null;
 
try {
 
m = FindMethod.getMethod(target, methodName, new Class[] { source });
 
} catch (Exception e) {
}
 
if (m == null) {
 
Class<?> primitive = getPrimitiveFrom(source);
 
if (primitive != null) {
 
try {
 
m = target.getMethod(methodName, new Class[] { primitive });
 
} catch (Exception e) {
}
 
}
}
 
if (m != null) {
m.setAccessible(true);
}
 
return m;
 
}
 
public static Field findFieldToInject(Class<?> target, String name, Class<?> source) {
 
Field f = getField(target, name);
 
if (f != null) {
 
Class<?> type = f.getType();
 
if (type.isAssignableFrom(source) || checkPrimitives(type, source)) {
 
f.setAccessible(true);
 
return f;
}
 
}
 
return null;
}
 
private static final boolean isBlank(Object value) {
 
if (value != null && value instanceof String) {
 
String s = ((String) value).trim();
 
if (s.length() == 0) return true;
}
 
return false;
}
 
public static boolean inject(Method m, Object target, Object value, boolean tryToConvert, boolean tryingToConvertBoolean) throws Exception {
 
Class<?> type = m.getParameterTypes()[0];
 
if (tryingToConvertBoolean) {
 
if (value == null && (type.equals(Boolean.class) || type.equals(boolean.class))) {
 
value = Boolean.FALSE;
 
} else {
 
// if trying to convert boolean, convert or don't do anything...
 
return false;
 
}
}
 
if (value == null
|| (type.isAssignableFrom(value.getClass()) || checkPrimitives(type, value.getClass()) || (tryToConvert && ((isBlank(value) && (value = shouldConvertToNull(value,
type)) == null) || (value = tryToConvert(value, type)) != null)))) {
 
try {
 
m.invoke(target, new Object[] { value });
 
return true;
 
} catch (Exception e) {
 
System.err.println("Error injecting by method: " + value + " in " + target + " thru " + m);
 
e.printStackTrace();
 
throw e;
 
}
}
 
return false;
 
}
 
public static boolean hasDefaultConstructor(Class<?> klass) {
 
try {
 
return klass.getConstructor((Class[]) null) != null;
 
} catch (Exception e) {
 
return false;
}
}
 
/**
* Extract the value of a property of a bean!
*
* @param bean
* the target bean
* @param nameProperty
* the property name
* @return they value as String. The method toString is always called to every property!
* @throws Exception
*/
public static String getProperty(Object bean, String nameProperty) throws Exception {
 
if (nameProperty == null || nameProperty.equals("")) return null;
 
String methodName = getter(nameProperty);
 
Class<?> clazz = bean.getClass();
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.getName().equals(methodName) && method.getParameterTypes().length == 0) {
Object value = method.invoke(bean, (Object[]) null);
if (value == null) return null;
return value.toString();
}
}
 
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.getName().equals(nameProperty)) {
Object value = field.get(bean);
if (value == null) return null;
return value.toString();
}
}
 
return null;
}
 
private static String getter(String name) {
StringBuilder sb = new StringBuilder(name.length() + 3);
 
sb.append("get").append(name.substring(0, 1).toUpperCase());
 
if (name.length() > 1) sb.append(name.substring(1));
return sb.toString();
}
 
public static void beanToMap(Object bean, Map<String, String> map) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
if (bean != null) {
 
for (Method method : bean.getClass().getMethods()) {
String name = method.getName();
 
if (name.length() > 3 && name.startsWith("get") && !name.equals("getClass") && method.getParameterTypes().length == 0) {
 
method.setAccessible(true);
Object value = method.invoke(bean, new Object[0]);
map.put(name, value.toString());
}
}
}
}
public static interface Provider {
public Object get(String key);
public boolean hasValue(String key);
}
 
public static void getObject(Object target, Provider provider, boolean tryField, String prefix, boolean tryToConvert, boolean convertBoolean, boolean allowRecursion)
throws Exception {
 
Class<?> targetClass = target.getClass();
 
Map<String, Object> setters, fields;
 
// see if we have these in cache...
 
synchronized (settersMaps) {
 
setters = settersMaps.get(targetClass);
 
fields = fieldsMaps.get(targetClass);
 
}
 
// if not in cache, prepare maps for injection...
 
if (setters == null) {
 
setters = new HashMap<String, Object>();
 
fields = null;
 
if (tryField) {
 
fields = new HashMap<String, Object>();
 
}
 
prepareForInjection(targetClass, setters, fields);
 
synchronized (settersMaps) {
 
settersMaps.put(targetClass, setters);
 
fieldsMaps.put(targetClass, fields);
 
}
}
 
Iterator<String> iter = setters.keySet().iterator();
 
while (iter.hasNext()) {
 
String var = iter.next();
 
boolean hasValue = provider.hasValue(var);
 
Object value = provider.get(var);
 
boolean tryingToConvertBoolean = false;
 
if (value == null && !hasValue) {
 
if (!convertBoolean) {
 
continue;
 
} else {
 
tryingToConvertBoolean = true;
}
 
}
 
// if (value == null) continue;
 
Object obj = setters.get(var);
 
// we may have a list of overloaded methods...
 
List<Method> list = null;
 
Method m = null;
 
if (obj instanceof List) {
 
list = (List<Method>) obj;
 
} else {
 
m = (Method) setters.get(var);
 
}
 
if (m != null) {
 
if (!inject(m, target, value, tryToConvert, tryingToConvertBoolean) && allowRecursion) {
 
// i did not inject... how about a VO object for this
// setter?
 
Class<?> type = m.getParameterTypes()[0];
 
if (!type.getName().startsWith("java.") && !type.isPrimitive() && hasDefaultConstructor(type)) {
 
Object param = type.newInstance();
 
InjectionUtils.getObject(param, provider, true, prefix, true, true, false); // no
// recursion...
 
inject(m, target, param, false, false);
}
}
 
} else {
 
Iterator<Method> it = list.iterator();
 
boolean injected = false;
 
while (it.hasNext()) {
 
m = it.next();
 
if (inject(m, target, value, tryToConvert, tryingToConvertBoolean)) {
 
injected = true;
 
break;
}
}
 
if (!injected && allowRecursion) {
 
// i could not inject anything... how about a VO object for
// this setter...
 
it = list.iterator();
 
while (it.hasNext()) {
 
m = (Method) it.next();
 
Class<?> type = m.getParameterTypes()[0];
 
if (!type.getName().startsWith("java.") && !type.isPrimitive() && hasDefaultConstructor(type)) {
 
Object param = type.newInstance();
 
InjectionUtils.getObject(param, provider, true, prefix, true, true, false); // no
// recursion...
 
if (inject(m, target, param, false, false)) {
 
break; // done...
}
}
}
}
}
}
 
if (fields != null) {
 
iter = fields.keySet().iterator();
 
while (iter.hasNext()) {
 
String var = iter.next();
 
boolean hasValue = provider.hasValue(var);
 
Object value = provider.get(var);
 
Field f = (Field) fields.get(var);
 
Class<?> type = f.getType();
 
// If there is no value in the action input, assume false for
// booleans...
// (checkboxes and radio buttons are not send when not
// marked...)
 
if (convertBoolean && value == null && !hasValue) {
 
if (type.equals(Boolean.class) || type.equals(boolean.class)) {
 
value = Boolean.FALSE;
}
 
}
 
if (value == null && !hasValue) continue;
 
// if (value == null) continue;
 
if (value == null
|| (type.isAssignableFrom(value.getClass()) || checkPrimitives(type, value.getClass()) || (tryToConvert && ((isBlank(value) && (value = shouldConvertToNull(
value, type)) == null) || (value = tryToConvert(value, type)) != null)))) {
 
try {
 
f.set(target, value);
 
} catch (Exception e) {
 
System.err.println("Error injecting by field: " + value + " in " + target);
 
e.printStackTrace();
 
throw e;
 
}
}
}
}
}
}
/trunk/src/main/java/org/mentacontainer/util/FindConstructor.java
New file
0,0 → 1,135
package org.mentacontainer.util;
import java.lang.reflect.Constructor;
import java.util.LinkedList;
import java.util.List;
 
/**
* Find constructor with polymorphism!
* Class.getConstructor only finds an exact match.
*
* @author Jon Skeet (http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/921ab91865c8cc2e/9e141d3d62e7cb3f)
*/
public class FindConstructor {
 
/**
* Finds the most specific applicable constructor
*
* @param source Class to find a constructor for
* @param parameterTypes Parameter types to search for
*/
public static Constructor<?> getConstructor(Class<?> source,
Class<?>[] parameterTypes)
throws NoSuchMethodException {
return internalFind(source.getConstructors(),
parameterTypes);
}
 
/**
* Finds the most specific applicable declared constructor
*
* @param source Class to find method in
* @param parameterTypes Parameter types to search for
*/
public static Constructor<?> getDeclaredConstructor(Class<?> source,
Class<?>[] parameterTypes)
throws NoSuchMethodException {
return internalFind(source.getDeclaredConstructors(),
parameterTypes);
}
 
/**
* Internal method to find the most specific applicable method
*/
private static Constructor<?> internalFind(Constructor<?>[] toTest,
Class<?>[] parameterTypes)
throws NoSuchMethodException {
int l = parameterTypes.length;
 
// First find the applicable methods
List<Constructor<?>> applicableMethods = new LinkedList<Constructor<?>>();
 
for (int i = 0; i < toTest.length; i++) {
// Check the parameters match
Class<?>[] params = toTest[i].getParameterTypes();
 
if (params.length != l)
continue;
int j;
 
for (j = 0; j < l; j++)
if (!params[j].isAssignableFrom(parameterTypes[j]))
break;
// If so, add it to the list
if (j == l)
applicableMethods.add(toTest[i]);
}
 
/*
* If we've got one or zero methods, we can finish
* the job now.
*/
int size = applicableMethods.size();
 
if (size == 0)
throw new NoSuchMethodException ("No such constructor!");
if (size == 1)
return applicableMethods.get(0);
 
/*
* Now find the most specific method. Do this in a very primitive
* way - check whether each method is maximally specific. If more
* than one method is maximally specific, we'll throw an exception.
* For a definition of maximally specific, see JLS section 15.11.2.2.
*
* I'm sure there are much quicker ways - and I could probably
* set the second loop to be from i+1 to size. I'd rather not though,
* until I'm sure...
*/
int maximallySpecific = -1; // Index of maximally specific method
 
for (int i = 0; i < size; i++) {
int j;
// In terms of the JLS, current is T
Constructor<?> current = applicableMethods.get(i);
Class<?>[] currentParams = current.getParameterTypes();
Class<?> currentDeclarer = current.getDeclaringClass();
 
for (j = 0; j < size; j++) {
if (i == j)
continue;
// In terms of the JLS, test is U
Constructor<?> test = applicableMethods.get(j);
Class<?>[] testParams = test.getParameterTypes();
Class<?> testDeclarer = test.getDeclaringClass();
 
// Check if T is a subclass of U, breaking if not
if (!testDeclarer.isAssignableFrom(currentDeclarer))
break;
 
// Check if each parameter in T is a subclass of the
// equivalent parameter in U
int k;
 
for (k = 0; k < l; k++)
if (!testParams[k].isAssignableFrom(currentParams[k]))
break;
if (k != l)
break;
}
// Maximally specific!
if (j == size) {
if (maximallySpecific != -1)
throw new NoSuchMethodException
("Ambiguous method search - more " +
"than one maximally specific method");
maximallySpecific = i;
}
}
if (maximallySpecific == -1)
throw new NoSuchMethodException ("No maximally specific method.");
return applicableMethods.get(maximallySpecific);
}
 
}
/trunk/src/main/java/org/mentacontainer/Interceptor.java
New file
0,0 → 1,36
package org.mentacontainer;
 
/**
* Some factories can also implement this interface to perform some cleanup
* when the instance is created or cleared. For example, a connection pool will want
* to know when the connection instance is cleared so it can return it to
* the pool.
*
* It makes more sense to use this interface for factories that will be placed
* in the THREAD scope, but you can also use it with other scopes as well.
*
* This is particular useful for the THREAD scope for dealing with thread pools, so
* when the thread is returned to the thread pool you will want to clear the THREAD
* scope. That's pretty much how web containers work: one thread per request coming from
* a thread pool.
*
* @author sergio.oliveira.jr@gmail.com
*
* @param <E>
*/
public interface Interceptor<E> {
/**
* This method will be called right after the getInstance() method returns a new instance from the factory.
*
* @param createdObject The object that was just returned by the factory.
*/
public void onCreated(E createdObject);
/**
* This method will be called right after the object is cleared from the scope.
*
* @param clearedObject The object that was cleared.
*/
public void onCleared(E clearedObject);
}
/trunk/pom.xml
New file
0,0 → 1,419
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>oss-parent</artifactId>
<groupId>org.sonatype.oss</groupId>
<version>3</version>
</parent>
<groupId>me.soliveirajr</groupId>
<artifactId>menta-container</artifactId>
<version>1.1.3-SNAPSHOT</version>
<name>MentaContainer</name>
<description>A IOC container as simple and pragmatic as it can get with programmatic configuration through a Fluent API.</description>
<url>http://maven.apache.org</url>
<licenses>
<license>
<name>GNU Lesser General Public License (LGPL), Version 2.1</name>
<url>http://www.fsf.org/licensing/licenses/lgpl.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<connection>scm:svn:svn://soliveirajr.com/mentacontainer/trunk</connection>
<developerConnection>scm:svn:svn://soliveirajr.com/mentacontainer/trunk</developerConnection>
<url>svn://soliveirajr.com/mentacontainer/trunk</url>
</scm>
<distributionManagement>
<repository>
<id>sonatype-nexus-staging</id>
<name>Nexus Release Repository</name>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
<snapshotRepository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<properties>
<build.final.name>mentacontainer</build.final.name>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<svn.tags>svn://soliveirajr.com/mentacontainer/tags</svn.tags>
<svn.url>svn://soliveirajr.com/mentacontainer/trunk</svn.url>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Maven Repository Switchboard</name>
<url>http://repo1.maven.org/maven2</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Maven Plugin Repository</name>
<url>http://repo1.maven.org/maven2</url>
</pluginRepository>
</pluginRepositories>
<build>
<finalName>mentacontainer</finalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.0</version>
<configuration>
<mavenExecutorId>forked-path</mavenExecutorId>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>mentacontainer-all</finalName>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>all</shadedClassifierName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<executions>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</execution>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</execution>
</executions>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<tagBase>svn://soliveirajr.com/mentacontainer/tags</tagBase>
<connectionUrl>scm:svn:svn://soliveirajr.com/mentacontainer/trunk</connectionUrl>
<mavenExecutorId>forked-path</mavenExecutorId>
</configuration>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<id>default-clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>default-install</id>
<phase>install</phase>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>default-resources</id>
<phase>process-resources</phase>
<goals>
<goal>resources</goal>
</goals>
</execution>
<execution>
<id>default-testResources</id>
<phase>process-test-resources</phase>
<goals>
<goal>testResources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7.2</version>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>default-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>default-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>2.0.1</version>
<executions>
<execution>
<id>default-site</id>
<phase>site</phase>
<goals>
<goal>site</goal>
</goals>
<configuration>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
<configuration>...</configuration>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</execution>
<execution>
<id>default-deploy</id>
<phase>site-deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
<configuration>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
<configuration>...</configuration>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</execution>
</executions>
<configuration>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.5</version>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
<configuration>...</configuration>
</reportPlugin>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
</plugin>
<plugin>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.5</version>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8</version>
</plugin>
</plugins>
</reporting>
<profiles>
<profile>
<id>release-sign-artifacts</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-gpg-plugin</artifactId>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
/trunk/readme.txt
1,2 → 1,2
MentaContainer 2010
MentaContainer 2010-2012
 
/.
Property changes:
Added: svn:ignore
+ target
.classpath
.project
.settings
site