Reflect the API changes because of FELIX-4509, and add a test triggering frame issues.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1592769 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/manipulator/manipulator/pom.xml b/ipojo/manipulator/manipulator/pom.xml
index b0bea2e..4bb1bbb 100644
--- a/ipojo/manipulator/manipulator/pom.xml
+++ b/ipojo/manipulator/manipulator/pom.xml
@@ -77,6 +77,14 @@
       <version>1.4</version>
       <scope>test</scope>
     </dependency>
+
+      <dependency>
+          <!-- used in some tests -->
+          <groupId>commons-codec</groupId>
+          <artifactId>commons-codec</artifactId>
+          <version>1.9</version>
+          <scope>test</scope>
+      </dependency>
   </dependencies>
   <build>
     <resources>
@@ -123,8 +131,8 @@
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
-          <source>1.6</source>
-          <target>1.6</target>
+          <source>1.7</source>
+          <target>1.7</target>
         </configuration>
       </plugin>
 
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ClassCheckerTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ClassCheckerTestCase.java
index 031b1cf..773a2a3 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ClassCheckerTestCase.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ClassCheckerTestCase.java
@@ -106,7 +106,7 @@
     }
 
     private byte[] manipulate(byte[] input) throws Exception {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         manipulator.prepare(input);
         return manipulator.manipulate(input);
     }
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/DirManipulationTest.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/DirManipulationTest.java
index 6a1304d..15a5285 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/DirManipulationTest.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/DirManipulationTest.java
@@ -21,12 +21,9 @@
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
-import java.util.jar.Manifest;
 
 import org.apache.felix.ipojo.manipulator.Pojoization;
 import org.junit.Test;
@@ -85,7 +82,7 @@
 		os.close();
 
 		// Issue directory manipulation
-		pojoizator.directoryPojoization(tmpDir, null, manifestFile);
+		pojoizator.directoryPojoization(tmpDir, null, manifestFile, null);
 
 		// Check if supplied manifest file is altered in place
 		BufferedReader fi = new BufferedReader(new FileReader(manifestFile));
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/InnerClassAdapterTest.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/InnerClassAdapterTest.java
index 4e81014..4496609 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/InnerClassAdapterTest.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/InnerClassAdapterTest.java
@@ -203,7 +203,7 @@
 
     @Test
     public void testManipulatingTheInner() throws Exception {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         String className = "test.PojoWithInner";
         byte[] origin = ManipulatorTest.getBytesFromFile(new File(baseClassDirectory + className.replace(".",
                 "/") + ".class"));
@@ -260,7 +260,7 @@
 
     @Test
     public void testInnerClasses() throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         String className = "test.inner.ComponentWithInnerClasses";
         ManipulatedClassLoader classloader = manipulate(className, manipulator);
 
@@ -287,11 +287,11 @@
     @Test
     public void testDoubleManipulation() throws IOException, ClassNotFoundException, NoSuchMethodException,
             IllegalAccessException, InvocationTargetException, InstantiationException {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         String className = "test.inner.ComponentWithInnerClasses";
         ManipulatedClassLoader classloader = manipulate(className, manipulator);
 
-        manipulator = new Manipulator();
+        manipulator = new Manipulator(this.getClass().getClassLoader());
         classloader = manipulate(className, manipulator, classloader);
 
         Class clazz = classloader.findClass(className);
@@ -316,7 +316,7 @@
     @Test
     public void testThatManipulationMetadataContainsTheInnerClasses() throws IOException, ClassNotFoundException,
             NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         String className = "test.inner.ComponentWithInnerClasses";
         manipulate(className, manipulator);
 
@@ -343,7 +343,7 @@
     @Test
     public void testThatTheClassContainsTheFlagsForTheInnerMethods() throws IOException, ClassNotFoundException,
             NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         String className = "test.inner.ComponentWithInnerClasses";
         ManipulatedClassLoader classLoader = manipulate(className, manipulator);
 
@@ -361,7 +361,7 @@
 
     @Test
     public void testThatStaticInnerClassesAreNotManipulated() throws Exception {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         String className = "test.inner.ComponentWithInnerClasses";
         ManipulatedClassLoader classLoader = manipulate(className, manipulator);
 
@@ -377,7 +377,7 @@
 
     @Test
     public void testThatAnonymousClassDeclaredInStaticFieldsAreNotManipulated() throws Exception {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         String className = "test.inner.ComponentWithInnerClasses";
         ManipulatedClassLoader classLoader = manipulate(className, manipulator);
 
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatorTest.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatorTest.java
index 5cc8828..03f9b4a 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatorTest.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatorTest.java
@@ -38,7 +38,7 @@
 public class ManipulatorTest extends TestCase {
 
     public void testClusterDaemon() throws Exception {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         byte[] origin = getBytesFromFile(new File("target/test-classes/test/ClusterDaemon.class"));
         manipulator.prepare(origin);
         byte[] clazz = manipulator.manipulate(origin);
@@ -63,8 +63,41 @@
 
     }
 
+    public void testCrypto() throws Exception {
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
+        byte[] origin = getBytesFromFile(new File("target/test-classes/test/frames/CryptoServiceSingleton.class"));
+        manipulator.prepare(origin);
+        byte[] clazz = manipulator.manipulate(origin);
+
+        ManipulatedClassLoader classloader = new ManipulatedClassLoader("test.frames.CryptoServiceSingleton", clazz);
+
+        //Assert.assertNotNull(manipulator.getManipulationMetadata());
+
+        //System.out.println(manipulator.getManipulationMetadata());
+
+
+        ClassReader reader = new ClassReader(clazz);
+        CheckClassAdapter.verify(reader, false, new PrintWriter(new File("/tmp/class_dump")));
+
+        Class cl = classloader.findClass("test.frames.CryptoServiceSingleton");
+        Assert.assertNotNull(cl);
+
+        Object instance = cl.newInstance();
+
+        Method method = cl.getMethod("encryptAESWithCBC", String.class, String.class);
+        final String salt = "0000000000000000";
+        String result = (String) method.invoke(instance, "hello", salt);
+        assertNotNull(result);
+
+        // The manipulation add stuff to the class.
+        //Assert.assertTrue(clazz.length > getBytesFromFile(new File("target/test-classes/test/ClusterDaemon.class")).length);
+
+        //Assert.assertNotNull(cl.newInstance());
+
+    }
+
     public void testManipulatingTheSimplePojo() throws Exception {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         byte[] origin = getBytesFromFile(new File("target/test-classes/test/SimplePojo.class"));
         manipulator.prepare(origin);
         byte[] clazz = manipulator.manipulate(origin);
@@ -117,7 +150,7 @@
     }
 
     public void testManipulatingTheNonSunPOJO() throws Exception {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         byte[] origin = getBytesFromFile(new File("target/test-classes/test/NonSunClass.class"));
         manipulator.prepare(origin);
         byte[] clazz = manipulator.manipulate(origin);
@@ -160,7 +193,7 @@
     }
 
     public void testManipulatingChild() throws Exception {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         byte[] origin = getBytesFromFile(new File("target/test-classes/test/Child.class"));
         manipulator.prepare(origin);
         byte[] clazz = manipulator.manipulate(origin);
@@ -209,7 +242,7 @@
     }
 
     public void testManipulatingWithConstructorModification() throws Exception {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         byte[] origin = getBytesFromFile(new File("target/test-classes/test/Child.class"));
         manipulator.prepare(origin);
         byte[] clazz = manipulator.manipulate(origin);
@@ -276,7 +309,7 @@
 
 
     public void testManipulatingWithNoValidConstructor() throws Exception {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         byte[] origin = getBytesFromFile(new File("target/test-classes/test/NoValidConstructor.class"));
         manipulator.prepare(origin);
         byte[] clazz = manipulator.manipulate(origin);
@@ -315,7 +348,7 @@
     }
 
      public void testConstructor() throws Exception {
-        Manipulator manipulator = new Manipulator();
+         Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
          byte[] origin = getBytesFromFile(new File("target/test-classes/test/ConstructorCheck.class"));
          manipulator.prepare(origin);
          byte[] clazz = manipulator.manipulate(origin);
@@ -344,7 +377,7 @@
      * https://issues.apache.org/jira/browse/FELIX-3621
      */
     public void testManipulatingDoubleArray() throws Exception {
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         byte[] origin = getBytesFromFile(new File("target/test-classes/test/DoubleArray.class"));
         manipulator.prepare(origin);
         byte[] clazz = manipulator.manipulate(origin);
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/PojoizationTest.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/PojoizationTest.java
index eb9930a..0e50111 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/PojoizationTest.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/PojoizationTest.java
@@ -35,7 +35,7 @@
 		File out = new File("target/test-classes/tests.manipulation-no-annotations-manipulated.jar");
 		out.delete();
 		File metadata = new File("target/test-classes/metadata.xml");
-		pojoization.pojoization(in, out, metadata);
+		pojoization.pojoization(in, out, metadata, null);
 
 		Assert.assertTrue(out.exists());
 	}
@@ -46,7 +46,7 @@
 		File in = new File("target/test-classes/tests.manipulator-annotations.jar");
 		File out = new File("target/test-classes/tests.manipulation-annotations-manipulated.jar");
 		out.delete();
-		pojoization.pojoization(in, out, (File) null);
+		pojoization.pojoization(in, out, (File) null, null);
 
 		Assert.assertTrue(out.exists());
 	}
@@ -57,7 +57,7 @@
 		File in = new File("target/test-classes/tests.manipulation.java5.jar");
 		File out = new File("target/test-classes/tests.manipulation.java5-manipulated.jar");
 		out.delete();
-		pojoization.pojoization(in, out, (File) null);
+		pojoization.pojoization(in, out, (File) null, null);
 
 		Assert.assertTrue(out.exists());
 	}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/RemanipulationTest.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/RemanipulationTest.java
index 202bf40..0e0c556 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/RemanipulationTest.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/RemanipulationTest.java
@@ -60,7 +60,7 @@
         AnnotationMetadataProvider provider = new AnnotationMetadataProvider(store, reporter);
         List<Element> originalMetadata = provider.getMetadatas();
         // 1.2 Manipulation
-        Manipulator manipulator = new Manipulator();
+        Manipulator manipulator = new Manipulator(this.getClass().getClassLoader());
         manipulator.prepare(origin);
         byte[] clazz = manipulator.manipulate(origin);
         Element originalManipulationMetadata = manipulator.getManipulationMetadata();
@@ -78,7 +78,7 @@
         provider = new AnnotationMetadataProvider(store, reporter);
         List<Element> metadataAfterOneManipulation = provider.getMetadatas();
         // 2.2 Manipulation
-        manipulator = new Manipulator();
+        manipulator = new Manipulator(this.getClass().getClassLoader());
         manipulator.prepare(clazz);
         byte[] clazz2 = manipulator.manipulate(clazz);
         Element manipulationMetadataAfterSecondManipulation = manipulator.getManipulationMetadata();
@@ -96,7 +96,7 @@
         provider = new AnnotationMetadataProvider(store, reporter);
         List<Element> metadataAfterTwoManipulation = provider.getMetadatas();
         // 3.2 Manipulation
-        manipulator = new Manipulator();
+        manipulator = new Manipulator(this.getClass().getClassLoader());
         manipulator.prepare(clazz2);
         byte[] clazz3 = manipulator.manipulate(clazz2);
         Element manipulationMetadataAfterThirdManipulation = manipulator.getManipulationMetadata();
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/ManipulationEngineTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/ManipulationEngineTestCase.java
index 6b74a1b..8166ac5 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/ManipulationEngineTestCase.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/ManipulationEngineTestCase.java
@@ -54,7 +54,7 @@
     private ManipulationResultVisitor result;
 
     @InjectMocks
-    private ManipulationEngine engine = new ManipulationEngine();
+    private ManipulationEngine engine = new ManipulationEngine(this.getClass().getClassLoader());
 
 
     @Override
diff --git a/ipojo/manipulator/manipulator/src/test/java/test/frames/CryptoServiceSingleton.java b/ipojo/manipulator/manipulator/src/test/java/test/frames/CryptoServiceSingleton.java
new file mode 100644
index 0000000..8db36a8
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/test/frames/CryptoServiceSingleton.java
@@ -0,0 +1,433 @@
+/*
+ * #%L
+ * Wisdom-Framework
+ * %%
+ * Copyright (C) 2013 - 2014 Wisdom Framework
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+package test.frames;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Instantiate;
+import org.apache.felix.ipojo.annotations.Provides;
+
+import javax.crypto.*;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.Charset;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+
+/**
+ * This component triggers some interesting frames issue.
+ */
+@Component
+@Provides
+@Instantiate(name = "crypto")
+public class CryptoServiceSingleton {
+
+    public static final String AES_CBC_ALGORITHM = "AES/CBC/PKCS5Padding";
+    public static final String AES_ECB_ALGORITHM = "AES";
+    private static final Charset UTF_8 = Charset.defaultCharset();
+    public static final String HMAC_SHA_1 = "HmacSHA1";
+    public static final String PBKDF_2_WITH_HMAC_SHA_1 = "PBKDF2WithHmacSHA1";
+
+    private int keySize;
+    private int iterationCount;
+    private Hash defaultHash;
+
+    private final String secret;
+
+    public CryptoServiceSingleton(String secret, Hash defaultHash,
+                                  Integer keySize, Integer iterationCount) {
+        this.secret = secret;
+        this.defaultHash = defaultHash;
+        this.keySize = keySize;
+        this.iterationCount = iterationCount;
+    }
+
+    public CryptoServiceSingleton() {
+        this(
+                "I;>qOs/VgFe?l@>Kn/RGa0p9b1ji?Kg7uhjAPHdIO8>@<em_AFs[BAMUQ0D]eOLV",
+                Hash.valueOf("MD5"),
+                128,
+                20);
+    }
+
+
+    /**
+     * Generate the AES key from the salt and the private key.
+     *
+     * @param salt       the salt (hexadecimal)
+     * @param privateKey the private key
+     * @return the generated key.
+     */
+    private SecretKey generateAESKey(String privateKey, String salt) {
+        try {
+            byte[] raw = Hex.decodeHex(salt.toCharArray());
+            KeySpec spec = new PBEKeySpec(privateKey.toCharArray(), raw, iterationCount, keySize);
+            SecretKeyFactory factory = SecretKeyFactory.getInstance(PBKDF_2_WITH_HMAC_SHA_1);
+            return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), AES_ECB_ALGORITHM);
+        } catch (DecoderException | NoSuchAlgorithmException | InvalidKeySpecException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Encrypt a String with the AES encryption advanced using 'AES/CBC/PKCS5Padding'. Unlike the regular
+     * encode/decode AES method using ECB (Electronic Codebook), it uses Cipher-block chaining (CBC). The salt must be
+     * valid hexadecimal String. This method uses parts of the application secret as private key and initialization
+     * vector.
+     *
+     * @param value The message to encrypt
+     * @param salt  The salt (hexadecimal String)
+     * @return encrypted String encoded using Base64
+     */
+    public String encryptAESWithCBC(String value, String salt) {
+        return encryptAESWithCBC(value, getSecretPrefix(), salt, getDefaultIV());
+    }
+
+    /**
+     * Encrypt a String with the AES encryption advanced using 'AES/CBC/PKCS5Padding'. Unlike the regular
+     * encode/decode AES method using ECB (Electronic Codebook), it uses Cipher-block chaining (CBC). The private key
+     * must have a length of 16 bytes, the salt and initialization vector must be valid hex Strings.
+     *
+     * @param value      The message to encrypt
+     * @param privateKey The private key
+     * @param salt       The salt (hexadecimal String)
+     * @param iv         The initialization vector (hexadecimal String)
+     * @return encrypted String encoded using Base64
+     */
+    public String encryptAESWithCBC(String value, String privateKey, String salt, String iv) {
+        SecretKey genKey = generateAESKey(privateKey, salt);
+        byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, genKey, iv, value.getBytes(UTF_8));
+        return new String(Base64.encodeBase64(encrypted), UTF_8);
+    }
+
+    /**
+     * Decrypt a String with the AES encryption advanced using 'AES/CBC/PKCS5Padding'. Unlike the regular
+     * encode/decode AES method using ECB (Electronic Codebook), it uses Cipher-block chaining (CBC). The salt and
+     * initialization vector must be valid hex Strings. This method use parts of the application secret as private
+     * key and the default initialization vector.
+     *
+     * @param value An encrypted String encoded using Base64.
+     * @param salt  The salt (hexadecimal String)
+     * @return The decrypted String
+     */
+    public String decryptAESWithCBC(String value, String salt) {
+        return decryptAESWithCBC(value, getSecretPrefix(), salt, getDefaultIV());
+    }
+
+    /**
+     * Decrypt a String with the AES encryption advanced using 'AES/CBC/PKCS5Padding'. Unlike the regular
+     * encode/decode AES method using ECB (Electronic Codebook), it uses Cipher-block chaining (CBC). The private key
+     * must have a length of 16 bytes, the salt and initialization vector must be valid hexadecimal Strings.
+     *
+     * @param value      An encrypted String encoded using Base64.
+     * @param privateKey The private key
+     * @param salt       The salt (hexadecimal String)
+     * @param iv         The initialization vector (hexadecimal String)
+     * @return The decrypted String
+     */
+    public String decryptAESWithCBC(String value, String privateKey, String salt, String iv) {
+        SecretKey key = generateAESKey(privateKey, salt);
+        byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, decodeBase64(value));
+        return new String(decrypted, UTF_8);
+    }
+
+    /**
+     * Utility method encrypting/decrypting the given message.
+     * The sense of the operation is specified using the `encryptMode` parameter.
+     *
+     * @param encryptMode  encrypt or decrypt mode ({@link javax.crypto.Cipher#DECRYPT_MODE} or
+     *                     {@link javax.crypto.Cipher#ENCRYPT_MODE}).
+     * @param generatedKey the generated key
+     * @param vector       the initialization vector
+     * @param message      the plain/cipher text to encrypt/decrypt
+     * @return the encrypted or decrypted message
+     */
+    private byte[] doFinal(int encryptMode, SecretKey generatedKey, String vector, byte[] message) {
+        try {
+            byte[] raw = Hex.decodeHex(vector.toCharArray());
+            Cipher cipher = Cipher.getInstance(AES_CBC_ALGORITHM);
+            cipher.init(encryptMode, generatedKey, new IvParameterSpec(raw));
+            return cipher.doFinal(message);
+        } catch (NoSuchAlgorithmException | NoSuchPaddingException | DecoderException | InvalidKeyException |
+                InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Sign a message using the application secret key (HMAC-SHA1).
+     */
+    public String sign(String message) {
+        return sign(message, secret.getBytes(UTF_8));
+    }
+
+    /**
+     * Sign a message with a key.
+     *
+     * @param message The message to sign
+     * @param key     The key to use
+     * @return The signed message (in hexadecimal)
+     */
+    public String sign(String message, byte[] key) {
+        try {
+            // Get an hmac_sha1 key from the raw key bytes
+            SecretKeySpec signingKey = new SecretKeySpec(key, HMAC_SHA_1);
+
+            // Get an hmac_sha1 Mac instance and initialize with the signing key
+            Mac mac = Mac.getInstance(HMAC_SHA_1);
+            mac.init(signingKey);
+
+            // Compute the hmac on input data bytes
+            byte[] rawHmac = mac.doFinal(message.getBytes(UTF_8));
+
+            // Convert raw bytes to Hex
+            byte[] hexBytes = new Hex().encode(rawHmac);
+
+            // Covert array of Hex bytes to a String
+            return new String(hexBytes, UTF_8);
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * Create a hash using the default hashing algorithm.
+     *
+     * @param input The password
+     * @return The password hash
+     */
+    public String hash(String input) {
+        return hash(input, defaultHash);
+    }
+
+    /**
+     * Create a hash using specific hashing algorithm.
+     *
+     * @param input    The password
+     * @param hashType The hashing algorithm
+     * @return The password hash
+     */
+    public String hash(String input, Hash hashType) {
+        try {
+            MessageDigest m = MessageDigest.getInstance(hashType.toString());
+            byte[] out = m.digest(input.getBytes(UTF_8));
+            return new String(Base64.encodeBase64(out), UTF_8);
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * Encrypt a String with the AES standard encryption (using the ECB mode) using the default secret (the
+     * application secret).
+     *
+     * @param value The String to encrypt
+     * @return An hexadecimal encrypted string
+     */
+    public String encryptAES(String value) {
+        return encryptAES(value, getSecretPrefix());
+    }
+
+    /**
+     * Encrypt a String with the AES standard encryption (using the ECB mode). Private key must have a length of 16 bytes.
+     *
+     * @param value      The String to encrypt
+     * @param privateKey The key used to encrypt
+     * @return An hexadecimal encrypted string
+     */
+    public String encryptAES(String value, String privateKey) {
+        try {
+            byte[] raw = privateKey.getBytes(UTF_8);
+            SecretKeySpec skeySpec = new SecretKeySpec(raw, AES_ECB_ALGORITHM);
+            Cipher cipher = Cipher.getInstance(AES_ECB_ALGORITHM);
+            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
+            return Hex.encodeHexString(cipher.doFinal(value.getBytes(UTF_8)));
+        } catch (NoSuchAlgorithmException | NoSuchPaddingException |
+                InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Decrypt a String with the standard AES encryption (using the ECB mode) using the default secret (the
+     * application secret).
+     *
+     * @param value An hexadecimal encrypted string
+     * @return The decrypted String
+     */
+    public String decryptAES(String value) {
+        return decryptAES(value, getSecretPrefix());
+    }
+
+    /**
+     * Decrypt a String with the standard AES encryption (using the ECB mode). Private key must have a length of 16
+     * bytes.
+     *
+     * @param value      An hexadecimal encrypted string
+     * @param privateKey The key used to encrypt
+     * @return The decrypted String
+     */
+    public String decryptAES(String value, String privateKey) {
+        try {
+            byte[] raw = privateKey.getBytes(UTF_8);
+            SecretKeySpec skeySpec = new SecretKeySpec(raw, AES_ECB_ALGORITHM);
+            Cipher cipher = Cipher.getInstance(AES_ECB_ALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
+            return new String(cipher.doFinal(Hex.decodeHex(value.toCharArray())), UTF_8);
+        } catch (NoSuchAlgorithmException | NoSuchPaddingException |
+                InvalidKeyException | BadPaddingException | IllegalBlockSizeException | DecoderException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Gets the 16 first characters of the application secret.
+     *
+     * @return the secret prefix.
+     */
+    private String getSecretPrefix() {
+        return secret.substring(0, 16);
+    }
+
+    /**
+     * Gets a segment of the application secret of 16 characters and encoded them in hexadecimal. The segment
+     * contains from the 16th to the 32th characters from the application secret (16 characters). The extracted
+     * segment is encoded in hexadecimal
+     *
+     * @return the default initialization vector.
+     */
+    private String getDefaultIV() {
+        return String.valueOf(Hex.encodeHex(secret.substring(16, 32).getBytes(UTF_8)));
+    }
+
+    /**
+     * Sign a token.  This produces a new token, that has this token signed with a nonce.
+     * <p/>
+     * This primarily exists to defeat the BREACH vulnerability, as it allows the token to effectively be random per
+     * request, without actually changing the value.
+     *
+     * @param token The token to sign
+     * @return The signed token
+     */
+    public String signToken(String token) {
+        long nonce = System.currentTimeMillis();
+        String joined = nonce + "-" + token;
+        return sign(joined) + "-" + joined;
+    }
+
+    /**
+     * Extract a signed token that was signed by {@link #signToken(String)}.
+     *
+     * @param token The signed token to extract.
+     * @return The verified raw token, or null if the token isn't valid.
+     */
+    public String extractSignedToken(String token) {
+        String[] chunks = token.split("-", 3);
+        String signature = chunks[0];
+        String nonce = chunks[1];
+        String raw = chunks[2];
+        if (constantTimeEquals(signature, sign(nonce + "-" + raw))) {
+            return raw;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Constant time equals method.
+     * <p/>
+     * Given a length that both Strings are equal to, this method will always run in constant time.
+     * This prevents timing attacks.
+     */
+    private boolean constantTimeEquals(String a, String b) {
+        if (a.length() != b.length()) {
+            return false;
+        } else {
+            int equal = 0;
+            for (int i = 0; i < a.length(); i++) {
+                equal = equal | a.charAt(i) ^ b.charAt(i);
+            }
+            return equal == 0;
+        }
+    }
+
+    /**
+     * Encode binary data to base64.
+     *
+     * @param value The binary data
+     * @return The base64 encoded String
+     */
+    public String encodeBase64(byte[] value) {
+        return new String(Base64.encodeBase64(value), UTF_8);
+    }
+
+    /**
+     * Decode a base64 value.
+     *
+     * @param value The base64 encoded String
+     * @return decoded binary data
+     */
+    public byte[] decodeBase64(String value) {
+        return Base64.decodeBase64(value.getBytes(UTF_8));
+    }
+
+    /**
+     * Build an hexadecimal MD5 hash for a String.
+     *
+     * @param value The String to hash
+     * @return An hexadecimal Hash
+     */
+    public String hexMD5(String value) {
+        try {
+            MessageDigest messageDigest = MessageDigest.getInstance(Hash.MD5.toString());
+            messageDigest.reset();
+            messageDigest.update(value.getBytes(UTF_8));
+            byte[] digest = messageDigest.digest();
+            return String.valueOf(Hex.encodeHex(digest));
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    /**
+     * Build an hexadecimal SHA1 hash for a String.
+     *
+     * @param value The String to hash
+     * @return An hexadecimal Hash
+     */
+    public String hexSHA1(String value) {
+        try {
+            MessageDigest md;
+            md = MessageDigest.getInstance(Hash.SHA1.toString());
+            md.update(value.getBytes(UTF_8));
+            byte[] digest = md.digest();
+            return String.valueOf(Hex.encodeHex(digest));
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ipojo/manipulator/manipulator/src/test/java/test/frames/Hash.java b/ipojo/manipulator/manipulator/src/test/java/test/frames/Hash.java
new file mode 100644
index 0000000..079c131
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/test/frames/Hash.java
@@ -0,0 +1,42 @@
+/*
+ * #%L
+ * Wisdom-Framework
+ * %%
+ * Copyright (C) 2013 - 2014 Wisdom Framework
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+package test.frames;
+
+/**
+ * Common hash algorithms.
+ */
+public enum Hash {
+
+    MD5("MD5"),
+    SHA1("SHA-1"),
+    SHA256("SHA-256"),
+    SHA512("SHA-512");
+
+    private String algorithm;
+
+    Hash(String algorithm) {
+        this.algorithm = algorithm;
+    }
+
+    @Override
+    public String toString() {
+        return this.algorithm;
+    }
+}