Coverage Report - org.webslinger.AbstractMappingWebslingerServletContextFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractMappingWebslingerServletContextFactory
0%
0/77
0%
0/11
0
AbstractMappingWebslingerServletContextFactory$1
0%
0/2
N/A
0
AbstractMappingWebslingerServletContextFactory$2
0%
0/2
N/A
0
AbstractMappingWebslingerServletContextFactory$3
0%
0/4
N/A
0
AbstractMappingWebslingerServletContextFactory$ContextKey
0%
0/13
0%
0/3
0
AbstractMappingWebslingerServletContextFactory$ContextTTLObject
0%
0/12
N/A
0
AbstractMappingWebslingerServletContextFactory$Layout
N/A
N/A
0
AbstractMappingWebslingerServletContextFactory$LayoutKey
0%
0/5
N/A
0
AbstractMappingWebslingerServletContextFactory$MappingKey
0%
0/6
N/A
0
 
 1  
 package org.webslinger;
 2  
 
 3  
 import java.io.IOException;
 4  
 import java.util.ArrayList;
 5  
 import java.util.Arrays;
 6  
 import java.util.HashMap;
 7  
 import java.util.Iterator;
 8  
 import java.util.Map;
 9  
 import java.util.Set;
 10  
 import java.util.concurrent.Callable;
 11  
 import java.util.concurrent.ExecutionException;
 12  
 import java.util.concurrent.Future;
 13  
 
 14  
 import javax.servlet.ServletConfig;
 15  
 import javax.servlet.ServletContext;
 16  
 import javax.servlet.ServletException;
 17  
 import javax.servlet.http.HttpServletRequest;
 18  
 import javax.servlet.http.HttpServletResponse;
 19  
 
 20  
 import org.apache.commons.vfs.FileObject;
 21  
 import org.apache.commons.vfs.FileSystemManager;
 22  
 
 23  
 import org.webslinger.lang.ConcurrentFreezableCache;
 24  
 import org.webslinger.lang.ExecutionPool;
 25  
 import org.webslinger.lang.Freezable;
 26  
 import org.webslinger.util.TTLObject;
 27  
 
 28  0
 public abstract class AbstractMappingWebslingerServletContextFactory extends AbstractWebslingerServletContextFactory {
 29  
     static {
 30  0
         TTLObject.setDefaultTTLForClass(ContextTTLObject.class, 60000);
 31  0
     }
 32  
 
 33  0
     protected final ConcurrentFreezableCache<String, ContextTTLObject> contextMapping = new ConcurrentFreezableCache<String, ContextTTLObject>(AbstractMappingWebslingerServletContextFactory.class, "contextMapping", null, ConcurrentFreezableCache.SOFT) {
 34  
         protected ContextTTLObject createValue(Object key, String hostName) {
 35  0
             return new ContextTTLObject(hostName, ((MappingKey) key).contextPath);
 36  
         }
 37  
     };
 38  0
     protected final ConcurrentFreezableCache<ContextKey, WebslingerServletContext> contexts = new ConcurrentFreezableCache<ContextKey, WebslingerServletContext>(AbstractMappingWebslingerServletContextFactory.class, "contexts", null, ConcurrentFreezableCache.SOFT) {
 39  
         protected WebslingerServletContext createValue(Object key, ContextKey frozen) throws Exception {
 40  0
             return newWebslingerServletContext(((LayoutKey) key).layout);
 41  
         }
 42  
     };
 43  
     protected String moduleBase;
 44  
 
 45  
     public void init(ServletConfig config, String moduleBase) throws ServletException, IOException {
 46  0
         this.moduleBase = moduleBase;
 47  0
         ArrayList<Future> futures = new ArrayList<Future>();
 48  
         try {
 49  0
             for (final Layout layout: getStartLayouts()) {
 50  0
                 futures.add(ExecutionPool.submit(new Callable<Void>() {
 51  
                     public Void call() throws Exception {
 52  0
                         WebslingerServletContext context = contexts.get(new LayoutKey(layout));
 53  0
                         initializeContext(context, layout);
 54  0
                         return null;
 55  
                     }
 56  
                 }));
 57  
             }
 58  
             try {
 59  0
                 for (Future future: futures) {
 60  0
                     future.get();
 61  
                 }
 62  0
             } catch (ExecutionException e) {
 63  0
                 throw e.getCause();
 64  0
             }
 65  0
         } catch (RuntimeException e) {
 66  0
             throw e;
 67  0
         } catch (IOException e) {
 68  0
             throw e;
 69  0
         } catch (ServletException e) {
 70  0
             throw e;
 71  0
         } catch (Error e) {
 72  0
             throw e;
 73  0
         } catch (Throwable e) {
 74  0
             throw (ServletException) new ServletException(e.getMessage()).initCause(e);
 75  0
         }
 76  0
     }
 77  
 
 78  
     protected abstract Layout[] getStartLayouts() throws Exception;
 79  
 
 80  
     public void destroy() {
 81  0
     }
 82  
 
 83  0
     protected static final class MappingKey implements Freezable<String> {
 84  
         protected final String hostName;
 85  
         protected final String contextPath;
 86  
 
 87  0
         protected MappingKey(String hostName, String contextPath) {
 88  0
             this.hostName = hostName;
 89  0
             this.contextPath = contextPath;
 90  0
         }
 91  
 
 92  
         public String freeze() {
 93  0
             return hostName;
 94  
         }
 95  
     }
 96  
 
 97  
     public WebslingerServletContext getWebslingerServletContext(HttpServletRequest request, HttpServletResponse response) throws ServletException {
 98  0
         String hostName = request.getServerName();
 99  0
         String contextPath = request.getContextPath();
 100  0
         if (contextPath == null || contextPath.length() == 0) contextPath = "/";
 101  
         try {
 102  0
             ContextTTLObject holder = contextMapping.get(new MappingKey(hostName, contextPath));
 103  0
             WebslingerServletContext context = holder.getObject();
 104  0
             initializeRequest(context, request);
 105  0
             return context;
 106  0
         } catch (RuntimeException e) {
 107  0
             throw e;
 108  0
         } catch (Exception e) {
 109  0
             throw (ServletException) new ServletException(e.getMessage()).initCause(e);
 110  
         }
 111  
     }
 112  
 
 113  
     protected interface Layout {
 114  
         String getId();
 115  
         String getTarget();
 116  
         String[] getBases();
 117  
     }
 118  
 
 119  
     // Note: contextPath never changes, we just have to fetch it from a request.
 120  
     protected WebslingerServletContext getContext(String hostName, String contextPath) throws Exception {
 121  0
         Layout layout = findLayout(hostName, contextPath);
 122  0
         WebslingerServletContext context = contexts.get(new LayoutKey(layout));
 123  0
         initializeContext(context, layout);
 124  0
         return context;
 125  
     }
 126  
 
 127  
     protected void initializeContext(WebslingerServletContext context, Layout layout) throws Exception {
 128  0
     }
 129  
 
 130  
     protected WebslingerServletContext newWebslingerServletContext(Layout layout) throws Exception {
 131  0
         FileObject root = getRoot(layout.getTarget(), moduleBase);
 132  0
         return newWebslingerServletContext(layout.getId(), root, resolveBases(root.getFileSystem().getFileSystemManager(), layout.getBases()));
 133  
     }
 134  
 
 135  
     protected FileObject[] resolveBases(FileSystemManager fsm, String[] bases) throws IOException {
 136  0
         FileObject[] fileBases = new FileObject[bases.length];
 137  0
         for (int i = 0; i < fileBases.length; i++) {
 138  0
             fileBases[i] = fsm.resolveFile(bases[i]);
 139  
         }
 140  0
         return fileBases;
 141  
     }
 142  
 
 143  
     protected abstract Set<String> getSuffixes() throws Exception;
 144  
 
 145  
     protected Layout findLayout(String hostName, String contextPath) throws Exception {
 146  0
         System.err.println("findLayout(" + hostName + ", " + contextPath + ")");
 147  0
         Layout layout = searchLayout(hostName, contextPath);
 148  0
         if (layout != null) return layout;
 149  
 OUTER:
 150  
         while (true) {
 151  0
             for (String suffix: getSuffixes()) {
 152  0
                 if (hostName.endsWith(suffix)) {
 153  0
                     hostName = hostName.substring(0, hostName.length() - suffix.length());
 154  0
                     continue OUTER;
 155  
                 }
 156  
             }
 157  0
             break;
 158  
         }
 159  0
         layout = searchLayout(hostName, contextPath);
 160  0
         if (layout != null) return layout;
 161  0
         System.err.println("returning default");
 162  0
         return searchLayout("*", contextPath);
 163  
     }
 164  
 
 165  
     protected Layout searchLayout(String hostName, String contextPath) throws Exception {
 166  0
         System.err.println("searchLayout(" + hostName + ", " + contextPath + ")");
 167  0
         StringBuilder pattern = new StringBuilder(hostName.length() + 1);
 168  0
         pattern.append('.').append(hostName);
 169  
         do {
 170  0
             System.err.println("1 checking(" + pattern + ")");
 171  0
             Layout layout = lookupLayout(pattern.toString(), contextPath);
 172  0
             if (layout != null) return layout;
 173  0
             pattern.deleteCharAt(0);
 174  0
             System.err.println("2 checking(" + pattern + ")");
 175  0
             layout = lookupLayout(pattern.toString(), contextPath);
 176  0
             if (layout != null) return layout;
 177  0
             int period = pattern.indexOf(".");
 178  0
             if (period == -1) break; // FIXME?
 179  0
             pattern.delete(0, period);
 180  0
         } while (true);
 181  0
         return null;
 182  
     }
 183  
 
 184  
     protected abstract Layout lookupLayout(String hostName, String contextPath) throws Exception;
 185  
 
 186  0
     private final class ContextTTLObject extends TTLObject<WebslingerServletContext> {
 187  
         protected final String hostName;
 188  
         protected final String contextPath;
 189  
 
 190  0
         protected ContextTTLObject(String hostName, String contextPath) {
 191  0
             this.hostName = hostName;
 192  0
             this.contextPath = contextPath;
 193  0
         }
 194  
 
 195  
         protected WebslingerServletContext load(WebslingerServletContext old) throws IOException {
 196  
             try {
 197  0
                 return getContext(hostName, contextPath);
 198  0
             } catch (IOException e) {
 199  0
                 throw e;
 200  0
             } catch (RuntimeException e) {
 201  0
                 throw e;
 202  0
             } catch (Exception e) {
 203  0
                 throw (IOException) new IOException(e.getMessage()).initCause(e);
 204  
             }
 205  
         }
 206  
     }
 207  
 
 208  0
     private final class LayoutKey implements Freezable<ContextKey> {
 209  
         protected final Layout layout;
 210  
 
 211  0
         protected LayoutKey(Layout layout) {
 212  0
             this.layout = layout;
 213  0
         }
 214  
 
 215  
         public ContextKey freeze() {
 216  0
             return new ContextKey(layout);
 217  
         }
 218  
     }
 219  
 
 220  0
     private final class ContextKey {
 221  
         private final String target;
 222  
         private final String[] bases;
 223  
         private final int hashCode;
 224  
 
 225  0
         protected ContextKey(Layout layout) {
 226  0
             target = layout.getTarget();
 227  0
             bases = layout.getBases();
 228  0
             int hashCode = target.hashCode();
 229  0
             for (String base: bases) {
 230  0
                 hashCode ^= base.hashCode();
 231  
             }
 232  0
             this.hashCode = hashCode;
 233  0
         }
 234  
 
 235  
         public int hashCode() {
 236  0
             return hashCode;
 237  
         }
 238  
 
 239  
         public boolean equals(Object o) {
 240  0
             if (!(o instanceof ContextKey)) return false;
 241  0
             ContextKey other = (ContextKey) o;
 242  0
             if (!target.equals(other.target)) return false;
 243  0
             return Arrays.equals(bases, other.bases);
 244  
         }
 245  
     }
 246  
 }