/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jackrabbit.mk;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.jackrabbit.mk.api.MicroKernel;
import org.apache.jackrabbit.mk.client.Client;
import org.apache.jackrabbit.mk.core.MicroKernelImpl;
import org.apache.jackrabbit.mk.fs.FileUtils;
import org.apache.jackrabbit.mk.index.IndexWrapper;
import org.apache.jackrabbit.mk.server.Server;
import org.apache.jackrabbit.mk.simple.SimpleKernelImpl;
import org.apache.jackrabbit.mk.util.ExceptionFactory;
import org.apache.jackrabbit.mk.wrapper.LogWrapper;
import org.apache.jackrabbit.mk.wrapper.SecurityWrapper;
import org.apache.jackrabbit.mk.wrapper.VirtualRepositoryWrapper;

/**
 * A factory to create a MicroKernel instance.
 */
public class MicroKernelFactory {

    private static final Map<String, SimpleKernelImpl> INSTANCES =
            new HashMap<String, SimpleKernelImpl>();

    /**
     * Get an instance. Supported URLs:
     * <ul>
     * <li>fs:target/mk-test (using the directory ./target/mk-test)</li>
     * <li>fs:target/mk-test;clean (same, but delete the old repository first)</li>
     * <li>fs:{homeDir} (use the system property homeDir or '.' if not set)</li>
     * <li>simple: (in-memory implementation)</li>
     * <li>simple:fs:target/temp (using the directory ./target/temp)</li>
     * </ul>
     *
     * @param url the repository URL
     * @return a new instance
     */
    public static synchronized MicroKernel getInstance(String url) {
        int colon = url.indexOf(':');
        if (colon == -1) {
            throw new IllegalArgumentException("Unknown repository URL: " + url);
        }

        String head = url.substring(0, colon);
        String tail = url.substring(colon + 1);
        if (head.equals("mem") || head.equals("simple")) {
            boolean clean = false;
            if (tail.endsWith(";clean")) {
                tail = tail.substring(0, tail.length() - ";clean".length());
                clean = true;
            }

            tail = tail.replaceAll("\\{homeDir\\}", System.getProperty("homeDir", "."));

            if (clean) {
                String dir = tail.substring(tail.lastIndexOf(':') + 1);
                try {
                    FileUtils.deleteRecursive(dir, false);
                } catch (Exception e) {
                    throw ExceptionFactory.convert(e);
                }
                INSTANCES.remove(tail);
            }

            SimpleKernelImpl instance = INSTANCES.get(tail);
            if (instance == null) {
                instance = new SimpleKernelImpl(tail);
                INSTANCES.put(tail, instance);
            }
            return instance;
        } else if (head.equals("log")) {
            return new LogWrapper(getInstance(tail));
        } else if (head.equals("sec")) {
            return SecurityWrapper.get(url);
        } else if (head.equals("virtual")) {
            return VirtualRepositoryWrapper.get(url);
        } else if (head.equals("index")) {
            return new IndexWrapper(getInstance(tail));
        } else if (head.equals("fs:")) {
            boolean clean = false;
            if (tail.endsWith(";clean")) {
                tail = tail.substring(0, tail.length() - ";clean".length());
                clean = true;
            }

            tail = tail.replaceAll("\\{homeDir\\}", System.getProperty("homeDir", "."));

            if (clean) {
                try {
                    FileUtils.deleteRecursive(tail + "/" + ".mk", false);
                } catch (IOException e) {
                    throw ExceptionFactory.convert(e);
                }
            }

            return new MicroKernelImpl(tail);
        } else if (head.equals("http")) {
            return new Client(url);
        } else if (head.equals("http-bridge")) {
            MicroKernel mk = getInstance(tail);

            final Server server = new Server(mk);
            try {
                server.start();
            } catch (IOException e) {
                throw new IllegalArgumentException(e.getMessage());
            }

            return new Client(server.getAddress()) {
                @Override
                public synchronized void dispose() {
                    super.dispose();
                    server.stop();
                }
            };
        } else {
            throw new IllegalArgumentException(url);
        }
    }

}

@@ -2596,16 +2596,37 @@
 simple%22)
+ %7C%7C head.equals(%22fs%22)
 ) %7B%0A    
@@ -2966,53 +2966,248 @@
  dir
- = tail.substring(tail.lastIndexOf(':') + 1);
+;%0A                if (head.equals(%22fs%22)) %7B%0A                    dir = tail + %22/.mk%22;%0A                %7D else %7B%0A                    dir = tail.substring(tail.lastIndexOf(':') + 1);%0A                    INSTANCES.remove(tail);%0A                %7D%0A
 %0A   
@@ -3409,36 +3409,98 @@
         
+%7D%0A%0A
     
-INSTANCES.remove
+        if (head.equals(%22fs%22)) %7B%0A                return new MicroKernelImpl
 (tail);%0A
@@ -3504,34 +3504,44 @@
 );%0A            %7D
-%0A%0A
+ else %7B%0A    
             Simp
@@ -3593,24 +3593,28 @@
             
+  
+  
 if (instance
@@ -3621,24 +3621,28 @@
  == null) %7B%0A
+    
             
@@ -3692,32 +3692,36 @@
                 
+    
 INSTANCES.put(ta
@@ -3739,34 +3739,42 @@
 e);%0A            
+ 
-%7D%0A
+   %7D%0A    
             retu
@@ -3786,16 +3786,30 @@
 stance;%0A
+            %7D%0A
         
@@ -4183,636 +4183,8 @@
 ));%0A
-        %7D else if (head.equals(%22fs:%22)) %7B%0A            boolean clean = false;%0A            if (tail.endsWith(%22;clean%22)) %7B%0A                tail = tail.substring(0, tail.length() - %22;clean%22.length());%0A                clean = true;%0A            %7D%0A%0A            tail = tail.replaceAll(%22%5C%5C%7BhomeDir%5C%5C%7D%22, System.getProperty(%22homeDir%22, %22.%22));%0A%0A            if (clean) %7B%0A                try %7B%0A                    FileUtils.deleteRecursive(tail + %22/%22 + %22.mk%22, false);%0A                %7D catch (IOException e) %7B%0A                    throw ExceptionFactory.convert(e);%0A                %7D%0A            %7D%0A%0A            return new MicroKernelImpl(tail);%0A
     

Drop MicroKernel.dispose()