001    package com.hammurapi.config.bootstrap;
002    
003    import java.net.URL;
004    import java.util.ArrayList;
005    import java.util.Collections;
006    import java.util.HashMap;
007    import java.util.List;
008    import java.util.Map;
009    import java.util.Properties;
010    import java.util.concurrent.Callable;
011    import java.util.concurrent.Executor;
012    
013    import org.apache.tools.ant.BuildException;
014    import org.apache.tools.ant.Project;
015    import org.apache.tools.ant.Task;
016    import org.apache.tools.ant.taskdefs.Property;
017    
018    import com.hammurapi.config.bootstrap.TokenExpander.TokenSource;
019    
020    public class BootstrapTask extends Task {
021            
022            private List<Property> properties = new ArrayList<Property>();
023            
024            public void addProperty(Property property) {
025                    properties.add(property);
026            }
027            
028            private String codebase;
029            
030            public void setCodebase(String codebase) {
031                    this.codebase = codebase;
032            }
033            
034            private String[] profile;
035            
036            public void setProfile(String profile) {
037                    this.profile = profile.split("/");
038            }
039            
040            private boolean inheritAll;
041            
042            public void setInheritAll(boolean inheritAll) {
043                    this.inheritAll = inheritAll;
044            }
045                    
046            private String configUrl;
047            
048            public void setConfigUrl(String configUrl) {
049                    this.configUrl = configUrl;
050            }
051            
052            private int threads;
053            
054            /**
055             * Thread pool size.
056             * @param threads
057             */
058            public void setThreads(int threads) {
059                    this.threads = threads;
060            }
061            
062            @SuppressWarnings("unchecked")
063            @Override
064            public void execute() throws BuildException {
065                    try {
066                            final Properties props = new Properties();
067                            if (inheritAll) {
068                                    props.putAll(getProject().getProperties());
069                            }
070                            for (Property property: properties) {
071                                    props.setProperty(property.getName(), property.getValue());
072                            }
073                            
074                            URL[] codebase = null;
075                            if (this.codebase!=null) {
076                                    String[] cbs=this.codebase.split(";");
077                                    codebase = new URL[cbs.length];
078                                    for (int j=0; j<cbs.length; ++j) {
079                                            codebase[j] = new URL(cbs[j]);
080                                    }
081                            }
082                            
083                            if (configUrl==null) {
084                                    System.err.println("Invalid command line parameters - missing configuration URL.");
085                                    System.exit(1);                 
086                            }
087                                    
088                            Bootstrapper<Object> factory = codebase==null ? new Bootstrapper<Object>() : new Bootstrapper<Object>(codebase);
089                            TokenSource tokens = new TokenSource() {
090            
091                                    public String getToken(String name) {
092                                            return props.getProperty(name);
093                                    }
094                                    
095                            };
096                            
097                            SimpleThreadPool executor = threads>0 ? new SimpleThreadPool(threads) : null;
098                            
099                            Map<Class<?>, Iterable<?>> services = new HashMap<Class<?>, Iterable<?>>();
100                            if (executor!=null) {
101                                    services.put(Executor.class, Collections.singleton(executor));
102                            }
103                            services.put(Project.class, Collections.singletonList(this.getProject()));
104                            FactoryClosure<Object> factoryClosure = factory.create(configUrl, tokens , profile, services, null);
105                            Object result = factoryClosure.create();
106                            try {
107                                    if (result instanceof Runnable) {
108                                            ((Runnable) result).run();
109                                    } else if (result instanceof Callable<?>) {
110                                            ((Callable) result).call();
111                                    } else {
112                                            throw new BuildException(result+" is not Runnable or Callable");
113                                    }
114                            } finally {                             
115                                    Destroyable toDestroy=factoryClosure.getDestroyable();
116                                    if (toDestroy!=null) {
117                                            toDestroy.destroy();
118                                    }
119                                    factoryClosure=null;
120                                    
121                                    if (executor!=null) {
122                                            executor.destroy();
123                                    }
124                            }
125                    } catch (BuildException e) {
126                            throw e;
127                    } catch (Exception e) {
128                            throw new BuildException(e);
129                    }
130            }
131    
132    }