You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by ag...@apache.org on 2008/06/28 21:18:57 UTC

svn commit: r672574 [10/16] - in /roller/planet/core/trunk: ./ lib/ lib/buildtime/ lib/jakarta-taglibs-standard-1.1.2/ lib/jakarta-taglibs-standard-1.1.2/lib/ lib/jakarta-taglibs-standard-1.1.2/tld/ lib/openjpa-0.9.7/ lib/rome-0.9/ lib/spring-1.2/ lib/...

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheManager.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheManager.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheManager.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CacheManager.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.planet.util.cache;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.planet.business.AggregatorFactory;
+import org.apache.roller.planet.config.PlanetConfig;
+import org.apache.roller.planet.pojos.Planet;
+import org.apache.roller.planet.pojos.PlanetGroup;
+
+
+/**
+ * A governing class for Roller cache objects.
+ *
+ * The purpose of the CacheManager is to provide a level of abstraction between
+ * classes that use a cache and the implementations of a cache.  This allows
+ * us to create easily pluggable cache implementations.
+ * 
+ * The other purpose is to provide a single interface for interacting with all
+ * Roller caches at the same time.  This is beneficial because as data
+ * changes in the system we often need to notify all caches that some part of
+ * their cached data needs to be invalidated, and the CacheManager makes that
+ * process easier.
+ */
+public class CacheManager {
+    
+    private static Log log = LogFactory.getLog(CacheManager.class);
+    
+    private static final String DEFAULT_FACTORY = 
+            "org.apache.roller.planet.util.cache.ExpiringLRUCacheFactoryImpl";
+    
+    // a reference to the cache factory in use
+    private static CacheFactory cacheFactory = null;
+    
+    // a set of all registered cache handlers
+    private static Set<CacheHandler> cacheHandlers = new HashSet<CacheHandler>();
+    
+    // a map of all registered caches
+    private static Map<String, Cache> caches = new HashMap<String, Cache>();
+    
+    
+    static {
+        // lookup what cache factory we want to use
+        String classname = AggregatorFactory.getAggregator().getConfig().getProperty("cache.defaultFactory");
+        
+        // use reflection to instantiate our factory class
+        try {
+            Class factoryClass = Class.forName(classname);
+            cacheFactory = (CacheFactory) factoryClass.newInstance();
+        } catch(ClassCastException cce) {
+            log.error("It appears that your factory does not implement "+
+                    "the CacheFactory interface",cce);
+        } catch(Exception e) {
+            log.error("Unable to instantiate cache factory ["+classname+"]"+
+                    " falling back on default", e);
+        }
+        
+        if(cacheFactory == null) try {
+            // hmm ... failed to load the specified cache factory
+            // lets try our default
+            Class factoryClass = Class.forName(DEFAULT_FACTORY);
+            cacheFactory = (CacheFactory) factoryClass.newInstance();
+        } catch(Exception e) {
+            log.fatal("Failed to instantiate a cache factory", e);
+            throw new RuntimeException(e);
+        }
+        
+        log.info("Cache Manager Initialized.");
+        log.info("Cache Factory = "+cacheFactory.getClass().getName());
+        
+        
+        // add custom handlers
+        String customHandlers = AggregatorFactory.getAggregator().getConfig().getProperty("cache.customHandlers");
+        if(customHandlers != null && customHandlers.trim().length() > 0) {
+            
+            String[] cHandlers = customHandlers.split(",");
+            for(int i=0; i < cHandlers.length; i++) {
+                // use reflection to instantiate the handler class
+                try {
+                    Class handlerClass = Class.forName(cHandlers[i]);
+                    CacheHandler customHandler = 
+                            (CacheHandler) handlerClass.newInstance();
+                    
+                    cacheHandlers.add(customHandler);
+                } catch(ClassCastException cce) {
+                    log.error("It appears that your handler does not implement "+
+                            "the CacheHandler interface",cce);
+                } catch(Exception e) {
+                    log.error("Unable to instantiate cache handler ["+cHandlers[i]+"]", e);
+                }
+            }
+        }
+    }
+    
+    
+    // a non-instantiable class
+    private CacheManager() {}
+    
+    
+    /**
+     * Ask the CacheManager to construct a cache.
+     *
+     * Normally the CacheManager will use whatever CacheFactory has been
+     * chosen for the system via the cache.defaultFactory property.
+     * However, it is possible to override the use of the default factory by
+     * supplying a "factory" property to this method.  The value should
+     * be the full classname for the factory you want to use for constructing
+     * the cache.
+     *
+     * example:
+     *   factory -> org.apache.roller.planet.util.cache.LRUCacheFactoryImpl
+     *
+     * This allows Roller admins the ability to choose a caching strategy to
+     * use for the whole system, but override it in certain places where they
+     * see fit.  It also allows users to write their own caching modifications
+     * and have them used only by specific caches.
+     */
+    public static Cache constructCache(CacheHandler handler, Map properties) {
+        
+        log.debug("Constructing new cache with props "+properties);
+        
+        Cache cache = null;
+        
+        if(properties != null && properties.containsKey("factory")) {
+            // someone wants a custom cache instance
+            String classname = (String) properties.get("factory");
+            
+            try {
+                // use reflection to instantiate the factory class
+                Class factoryClass = Class.forName(classname);
+                CacheFactory factory = (CacheFactory) factoryClass.newInstance();
+                
+                // now ask for a new cache
+                cache = factory.constructCache(properties);
+            } catch(ClassCastException cce) {
+                log.error("It appears that your factory ["+classname+
+                        "] does not implement the CacheFactory interface",cce);
+            } catch(Exception e) {
+                log.error("Unable to instantiate cache factory ["+classname+
+                        "] falling back on default", e);
+            }
+        }
+        
+        if(cache == null) {
+            // ask our default cache factory for a new cache instance
+            cache = cacheFactory.constructCache(properties);
+        }
+        
+        if(cache != null) {
+            caches.put(cache.getId(), cache);
+            
+            // register the handler for this new cache
+            if(handler != null) {
+                cacheHandlers.add(handler);
+            }
+        }
+
+        return cache;
+    }
+    
+    
+    /**
+     * Register a CacheHandler to listen for object invalidations.
+     *
+     * This is here so that it's possible to to add classes which would respond
+     * to object invalidations without necessarily having to create a cache.
+     *
+     * An example would be a handler designed to notify other machines in a 
+     * cluster when an object has been invalidated, or possibly the search
+     * index management classes are interested in knowing when objects are
+     * invalidated.
+     */
+    public static void registerHandler(CacheHandler handler) {
+        
+        log.debug("Registering handler "+handler);
+        
+        if(handler != null) {
+            cacheHandlers.add(handler);
+        }
+    }
+    
+    
+    public static void invalidate(Planet planet) {
+        
+        log.debug("invalidating entry = "+planet.getHandle());
+        
+        Iterator handlers = cacheHandlers.iterator();
+        while(handlers.hasNext()) {
+            ((CacheHandler) handlers.next()).invalidate(planet);
+        }
+    }
+    
+    
+    public static void invalidate(PlanetGroup group) {
+        
+        log.debug("invalidating website = "+group.getHandle());
+        
+        Iterator handlers = cacheHandlers.iterator();
+        while(handlers.hasNext()) {
+            ((CacheHandler) handlers.next()).invalidate(group);
+        }
+    }
+
+    
+    /**
+     * Flush the entire cache system.
+     */
+    public static void clear() {
+        
+        // loop through all caches and trigger a clear
+        Cache cache = null;
+        Iterator cachesIT = caches.values().iterator();
+        while(cachesIT.hasNext()) {
+            cache = (Cache) cachesIT.next();
+            
+            cache.clear();
+        }
+    }
+    
+    
+    /**
+     * Flush a single cache.
+     */
+    public static void clear(String cacheId) {
+        
+        Cache cache = caches.get(cacheId);
+        if(cache != null) {
+            cache.clear();
+        }
+    }
+    
+    
+    /**
+     * Compile stats from all registered caches.
+     *
+     * This is basically a hacky version of instrumentation which is being
+     * thrown in because we don't have a full instrumentation strategy yet.
+     * This is here with the full expectation that it will be replaced by
+     * something a bit more elaborate, like JMX.
+     */
+    public static Map<String, Map> getStats() {
+        
+        Map<String, Map> allStats = new HashMap<String, Map>();
+        
+        Cache cache = null;
+        Iterator cachesIT = caches.values().iterator();
+        while(cachesIT.hasNext()) {
+            cache = (Cache) cachesIT.next();
+            
+            allStats.put(cache.getId(), cache.getStats());
+        }
+        
+        return allStats;
+    }
+    
+    
+    /**
+     * Place to do any cleanup tasks for cache system.
+     */
+    public static void shutdown() {
+        // no-op
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CachedContent.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CachedContent.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CachedContent.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/CachedContent.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.planet.util.cache;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * A utility class for storing cached content written to a java.io.Writer.
+ */
+public class CachedContent implements Serializable {
+    
+    private static Log log = LogFactory.getLog(CachedContent.class);
+    
+    // default to an 8K buffered cache
+    public static final int DEFAULT_SIZE = 8192;
+    
+    // the byte array we use to maintain the cached content
+    private byte[] content = new byte[0];
+    
+    // content-type of data in byte array
+    private String contentType = null;
+    
+    // Use a byte array output stream to cached the output bytes
+    private transient ByteArrayOutputStream outstream = null;
+    
+    // The PrintWriter that users will be writing to
+    private transient PrintWriter cachedWriter = null;
+    
+    
+    public CachedContent(int size) {
+        
+        // construct output stream
+        if(size > 0) {
+            this.outstream = new ByteArrayOutputStream(size);
+        } else {
+            this.outstream = new ByteArrayOutputStream(DEFAULT_SIZE);
+        }
+        
+        // construct writer from output stream
+        try {
+            this.cachedWriter =
+                    new PrintWriter(new OutputStreamWriter(this.outstream, "UTF-8"));
+        } catch(UnsupportedEncodingException e) {
+            // shouldn't be possible, java always supports utf-8
+            throw new RuntimeException("Encoding problem", e);
+        }
+    }
+    
+    public CachedContent(int size, String contentType) {
+        this(size);
+        this.contentType = contentType;
+    }
+    
+    
+    /**
+     * Get the content cached in this object as a byte array.  If you convert
+     * this back to a string yourself, be sure to re-encode in "UTF-8".
+     *
+     * NOTE: the content is only a representation of the data written to the
+     *       enclosed Writer up until the last call to flush().
+     */
+    public byte[] getContent() {
+        return this.content;
+    }
+    
+    
+    /**
+     * Get the content cached in this object as a String.
+     *
+     * NOTE: the content is only a representation of the data written to the
+     *       enclosed Writer up until the last call to flush().
+     */
+    public String getContentAsString() {
+        try {
+            return new String(this.content,"UTF-8");
+        } catch (UnsupportedEncodingException uex) {
+            // shouldn't ever happen - violates Java Spec.
+            throw new RuntimeException(uex);
+        }
+    }
+    
+    
+    public PrintWriter getCachedWriter() {
+        return cachedWriter;
+    }
+    
+    
+    public String getContentType() {
+        return contentType;
+    }
+    
+    
+    /**
+     * Called to flush any output in the cached Writer to
+     * the cached content for more permanent storage.
+     *
+     * @throws IllegalStateException if calling flush() after a close()
+     */
+    public void flush() {
+        
+        if(this.outstream == null) {
+            throw new IllegalStateException("Cannot flush() after a close()!");
+        }
+        
+        this.cachedWriter.flush();
+        this.content = this.outstream.toByteArray();
+        
+        log.debug("FLUSHED "+this.content.length);
+    }
+    
+    
+    /**
+     * Close this CachedContent from further writing.
+     */
+    public void close() throws IOException {
+        
+        if(this.cachedWriter != null) {
+            this.cachedWriter.flush();
+            this.cachedWriter.close();
+            this.cachedWriter = null;
+        }
+        
+        if(this.outstream != null) {
+            this.content = this.outstream.toByteArray();
+            this.outstream.close();
+            this.outstream = null;
+        }
+        
+        log.debug("CLOSED");
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringCacheEntry.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringCacheEntry.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringCacheEntry.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringCacheEntry.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.planet.util.cache;
+
+import java.io.Serializable;
+
+
+/**
+ * A cache entry that expires.
+ *
+ * We use this class to wrap objects being cached and associate a timestamp
+ * and timeout period with them so we can know when they expire.
+ */
+public class ExpiringCacheEntry implements Serializable {
+    
+    private Object value;
+    private long timeCached = -1;
+    private long timeout = 0;
+    
+    
+    public ExpiringCacheEntry(Object value, long timeout) {
+        this.value = value;
+        
+        // make sure that we don't support negative values
+        if(timeout > 0) {
+            this.timeout = timeout;
+        }
+        
+        this.timeCached = System.currentTimeMillis();
+    }
+    
+    
+    public long getTimeCached() {
+        return this.timeCached;
+    }
+    
+    
+    public long getTimeout() {
+        return this.timeout;
+    }
+    
+    
+    /**
+     * Retrieve the value of this cache entry.
+     *
+     * If the value has expired then we return null.
+     */
+    public Object getValue() {
+        if(this.hasExpired()) {
+            return null;
+        } else {
+            return this.value;
+        }
+    }
+    
+    
+    /**
+     * Determine if this cache entry has expired.
+     */
+    public boolean hasExpired() {
+        
+        long now = System.currentTimeMillis();
+        
+        return ((this.timeCached + this.timeout) < now);
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringLRUCacheFactoryImpl.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringLRUCacheFactoryImpl.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringLRUCacheFactoryImpl.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringLRUCacheFactoryImpl.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.planet.util.cache;
+
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * Roller Expiring LRU cache factory.
+ */
+public class ExpiringLRUCacheFactoryImpl implements CacheFactory {
+    
+    private static Log log = LogFactory.getLog(ExpiringLRUCacheFactoryImpl.class);
+    
+    
+    // protected so only the CacheManager can instantiate us
+    protected ExpiringLRUCacheFactoryImpl() {}
+    
+    
+    /**
+     * Construct a new instance of a Roller Expiring LRUCache.
+     */
+    public Cache constructCache(Map properties) {
+        
+        int size = 100;
+        long timeout = 15 * 60;
+        String id = "unknown";
+        
+        try {
+            size = Integer.parseInt((String) properties.get("size"));
+        } catch(Exception e) {
+            // ignored
+        }
+        
+        try {
+            timeout = Long.parseLong((String) properties.get("timeout"));
+        } catch(Exception e) {
+            // ignored
+        }
+        
+        String cacheId = (String) properties.get("id");
+        if(cacheId != null) {
+            id = cacheId;
+        }
+        
+        Cache cache = new ExpiringLRUCacheImpl(id, size, timeout);
+        
+        log.debug("new cache constructed. size="+size+", timeout="+timeout);
+        
+        return cache;
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringLRUCacheImpl.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringLRUCacheImpl.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringLRUCacheImpl.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/ExpiringLRUCacheImpl.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.planet.util.cache;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * An LRU cache where entries expire after a given timeout period.
+ */
+public class ExpiringLRUCacheImpl extends LRUCacheImpl {
+    
+    private static Log log = LogFactory.getLog(ExpiringLRUCacheImpl.class);
+    
+    private long timeout = 0;
+    
+    
+    public ExpiringLRUCacheImpl(String id) {
+        
+        super(id);
+        this.timeout = 60 * 60 * 1000;
+    }
+    
+    
+    public ExpiringLRUCacheImpl(String id, int maxsize, long timeout) {
+        
+        super(id, maxsize);
+        
+        // timeout is specified in seconds; only positive values allowed
+        if(timeout > 0) {
+            this.timeout = timeout * 1000;
+        }
+    }
+    
+    
+    /**
+     * Store an entry in the cache.
+     *
+     * We wrap the cached object in our ExpiringCacheEntry object so that we
+     * can track when the entry has expired.
+     */
+    @Override
+    public synchronized void put(String key, Object value) {
+        
+        ExpiringCacheEntry entry = new ExpiringCacheEntry(value, this.timeout);
+        super.put(key, entry);
+    }
+    
+    
+    /**
+     * Retrieve an entry from the cache.
+     *
+     * This LRU cache supports timeouts, so if the cached object has expired
+     * then we return null, just as if the entry wasn't found.
+     */
+    @Override
+    public Object get(String key) {
+        
+        Object value = null;
+        ExpiringCacheEntry entry = null;
+        
+        synchronized(this) {
+            entry = (ExpiringCacheEntry) super.get(key);
+        }
+        
+        if (entry != null) {
+            
+            value = entry.getValue();
+            
+            // if the value is null then that means this entry expired
+            if (value == null) {
+                log.debug("EXPIRED ["+key+"]");
+                hits--;
+                super.remove(key);
+            }
+        }
+        
+        return value;
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LRUCacheFactoryImpl.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LRUCacheFactoryImpl.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LRUCacheFactoryImpl.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LRUCacheFactoryImpl.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.planet.util.cache;
+
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * Roller LRU Cache factory.
+ */
+public class LRUCacheFactoryImpl implements CacheFactory {
+    
+    private static Log log = LogFactory.getLog(LRUCacheFactoryImpl.class);
+    
+    
+    // protected so that only the CacheManager can instantiate us
+    protected LRUCacheFactoryImpl() {}
+    
+    
+    /**
+     * Construct a new instance of a Roller LRUCache.
+     */
+    public Cache constructCache(Map properties) {
+        
+        int size = 100;
+        String id = "unknown";
+        
+        try {
+            size = Integer.parseInt((String) properties.get("size"));
+        } catch(Exception e) {
+            // ignored
+        }
+        
+        String cacheId = (String) properties.get("id");
+        if(cacheId != null) {
+            id = cacheId;
+        }
+        
+        Cache cache = new LRUCacheImpl(id, size);
+        
+        log.debug("new cache constructed. size="+size);
+        
+        return cache;
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LRUCacheImpl.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LRUCacheImpl.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LRUCacheImpl.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LRUCacheImpl.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.planet.util.cache;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * A simple LRU Cache.
+ */
+public class LRUCacheImpl implements Cache {
+    
+    private static Log log = LogFactory.getLog(LRUCacheImpl.class);
+    
+    private String id = null;
+    private Map cache = null;
+    
+    // for metrics
+    protected double hits = 0;
+    protected double misses = 0;
+    protected double puts = 0;
+    protected double removes = 0;
+    protected Date startTime = new Date();
+    
+    
+    protected LRUCacheImpl(String id) {
+        
+        this.id = id;
+        this.cache = Collections.synchronizedMap(new LRULinkedHashMap(100));
+    }
+    
+    
+    protected LRUCacheImpl(String id, int maxsize) {
+        
+        this.id = id;
+        this.cache = Collections.synchronizedMap(new LRULinkedHashMap(maxsize));
+    }
+    
+    
+    public String getId() {
+        return this.id;
+    }
+    
+    
+    /**
+     * Store an entry in the cache.
+     */
+    public synchronized void put(String key, Object value) {
+        
+        this.cache.put(key, value);
+        puts++;
+    }
+    
+    
+    /**
+     * Retrieve an entry from the cache.
+     */
+    public synchronized Object get(String key) {
+        
+        Object obj = this.cache.get(key);
+        
+        // for metrics
+        if(obj == null) {
+            misses++;
+        } else {
+            hits++;
+        }
+        
+        return obj;
+    }
+    
+    
+    public synchronized void remove(String key) {
+        
+        this.cache.remove(key);
+        removes++;
+    }
+    
+    
+    public synchronized void clear() {
+        
+        this.cache.clear();
+        
+        // clear metrics
+        hits = 0;
+        misses = 0;
+        puts = 0;
+        removes = 0;
+        startTime = new Date();
+    }
+    
+    
+    public Map getStats() {
+        
+        Map stats = new HashMap();
+        stats.put("startTime", this.startTime);
+        stats.put("hits", new Double(this.hits));
+        stats.put("misses", new Double(this.misses));
+        stats.put("puts", new Double(this.puts));
+        stats.put("removes", new Double(this.removes));
+        
+        // calculate efficiency
+        if((misses - removes) > 0) {
+            double efficiency = hits / (misses + hits);
+            stats.put("efficiency", new Double(efficiency * 100));
+        }
+        
+        return stats;
+    }
+    
+    
+    // David Flanaghan: http://www.davidflanagan.com/blog/000014.html
+    private static class LRULinkedHashMap extends LinkedHashMap {
+        protected int maxsize;
+        
+        public LRULinkedHashMap(int maxsize) {
+            super(maxsize * 4 / 3 + 1, 0.75f, true);
+            this.maxsize = maxsize;
+        }
+        
+        protected boolean removeEldestEntry(Map.Entry eldest) {
+            return this.size() > this.maxsize;
+        }
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LazyExpiringCacheEntry.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LazyExpiringCacheEntry.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LazyExpiringCacheEntry.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/cache/LazyExpiringCacheEntry.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  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.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.planet.util.cache;
+
+import java.io.Serializable;
+
+
+/**
+ * A cache entry that is meant to expire in a lazy fashion.
+ *
+ * The way to use this class is to wrap the object you want to cache in an
+ * instance of this class and store that in your cache.  Then when you want
+ * to retrieve this entry you must input a last-expired time which can be
+ * compared against the time this entry was cached to determine if the cached
+ * entry is "fresh".  If the object is not fresh then we don't return it.
+ *
+ * This essentially allows us to track when an object is cached and then before
+ * we can retrieve that cached object we must compare it with it's last known
+ * invalidation time to make sure it hasn't expired.  This is useful because
+ * instead of actively purging lots of cached objects from the cache at 
+ * invalidation time, we can now be lazy and just invalidate them when we
+ * actually try to retrieve the cached object.
+ *
+ * This is useful for Roller because we will no longer have to iterate through
+ * the list of cached objects and inspect the keys to figure out what items to
+ * invalidate.  Instead we can just sit back and let the items be invalidated as
+ * we try to use them.
+ */
+public class LazyExpiringCacheEntry implements Serializable {
+    
+    private Object value = null;
+    private long timeCached = -1;
+    
+    
+    public LazyExpiringCacheEntry(Object item) {
+        this.value = item;
+        this.timeCached = System.currentTimeMillis();
+    }
+    
+    
+    /**
+     * Retrieve the value of this cache entry if it is still "fresh".
+     *
+     * If the value has expired then we return null.
+     */
+    public Object getValue(long lastInvalidated) {
+        if(this.isInvalid(lastInvalidated)) {
+            return null;
+        } else {
+            return this.value;
+        }
+    }
+    
+    
+    /**
+     * Determine if this cache entry has expired.
+     */
+    public boolean isInvalid(long lastInvalidated) {
+        
+        return (this.timeCached < lastInvalidated);
+    }
+
+    
+    public long getTimeCached() {
+        return timeCached;
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/MailResources.properties
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/MailResources.properties?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/MailResources.properties (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/MailResources.properties Sat Jun 28 12:18:17 2008
@@ -0,0 +1,11 @@
+#
+# Resource Bundle for email messages
+#
+
+PlanetInvite.subject=Invitation to join planet "{0}"
+PlanetInvite.body=\
+Hi there {0}, \n\
+\n\
+{1} has invited you to be a member of planet "{2}". \n\
+\n\
+Click the following link and login to accept or decline this invitation <{3}>.\n

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/PlanetMailer.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/PlanetMailer.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/PlanetMailer.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/PlanetMailer.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,79 @@
+
+package org.apache.roller.planet.util.mail;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import org.apache.roller.planet.business.MailProvider;
+import org.apache.roller.planet.config.PlanetConfig;
+import org.apache.roller.planet.pojos.Planet;
+import org.apache.roller.planet.pojos.User;
+import org.apache.roller.planet.util.MailUtil;
+
+
+/**
+ * A utility class for sending out system email notifications.
+ * 
+ * This class handles the actual formation of the messages and then uses the
+ * MailUtil class for transport.
+ *
+ * @author ag92114
+ */
+public class PlanetMailer {
+    
+    private final MailProvider mailProvider;
+    private final PlanetConfig planetConfig;
+    
+    
+    public PlanetMailer(MailProvider provider, PlanetConfig config) {
+        this.mailProvider = provider;
+        this.planetConfig = config;
+    }
+    
+    
+    /**
+     * Send a planet invitation email.
+     */
+    public void sendPlanetInvitation(User invitor, User invitee, Planet planet)
+            throws PlanetMailerException {
+        
+        Session mailSession = mailProvider.getSession();
+        if(mailSession == null) {
+            throw new PlanetMailerException("Cannot sent mail, Planet MailProvider not configured.");
+        }
+        
+        // load our email messages resource bundle
+        ResourceBundle resources = ResourceBundle.getBundle("org/apache/roller/planet/util/mail/MailResources");
+
+        // URL to main menu for invitation accept/decline
+        String url = planetConfig.getProperty("site.absoluteurl") + "/planet-ui/menu.rol";
+
+        // prepare the email message
+        String to = invitee.getEmailAddress();
+        String from = invitor.getEmailAddress();
+        String cc = invitor.getEmailAddress();
+        String bcc = null;
+        String subject = MessageFormat.format(
+                resources.getString("PlanetInvite.subject"),
+                new Object[]{planet.getTitle()});
+        String content = MessageFormat.format(
+                resources.getString("PlanetInvite.body"),
+                new Object[]{
+            invitee.getFullName(),
+            invitor.getFullName(),
+            planet.getTitle(),
+            url
+        });
+        
+        // try sending the email
+        try {
+            MailUtil.sendTextMessage(mailSession, from, to, cc, bcc, subject, content);
+            
+        } catch (MessagingException e) {
+            throw new PlanetMailerException("Mail sending failed, "
+                    + "likely a MailProvider configuration or mail server problem.", e);
+        }
+    }
+    
+}

Added: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/PlanetMailerException.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/PlanetMailerException.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/PlanetMailerException.java (added)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/mail/PlanetMailerException.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,22 @@
+
+package org.apache.roller.planet.util.mail;
+
+import org.apache.roller.planet.PlanetException;
+
+
+/**
+ * Exception thrown by PlanetMailer class.
+ *
+ * @author ag92114
+ */
+public class PlanetMailerException extends PlanetException {
+    
+    public PlanetMailerException(String msg) {
+        super(msg);
+    }
+    
+    public PlanetMailerException(String msg, Throwable t) {
+        super(msg, t);
+    }
+    
+}

Modified: roller/planet/core/trunk/src/java/org/apache/roller/planet/util/rome/DiskFeedInfoCache.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/src/java/org/apache/roller/planet/util/rome/DiskFeedInfoCache.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/src/java/org/apache/roller/planet/util/rome/DiskFeedInfoCache.java (original)
+++ roller/planet/core/trunk/src/java/org/apache/roller/planet/util/rome/DiskFeedInfoCache.java Sat Jun 28 12:18:17 2008
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.roller.planet.util.rome;
 
 import java.io.File;
@@ -23,75 +24,144 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.net.URL;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
 import com.sun.syndication.fetcher.impl.FeedFetcherCache;
 import com.sun.syndication.fetcher.impl.SyndFeedInfo;
 import org.apache.roller.planet.util.Utilities;
 
+
 /**
+ * File based cache used by a Rome feed fetcher.
+ * 
  * @author David M. Johnson
  */
-public class DiskFeedInfoCache implements FeedFetcherCache
-{
-    private static Log logger = 
-        LogFactory.getFactory().getInstance(DiskFeedInfoCache.class);
-    
-    protected String cachePath = null;
-    public DiskFeedInfoCache(String cachePath)
-    {
-        this.cachePath = cachePath;
+public class DiskFeedInfoCache implements FeedFetcherCache {
+
+    private static Log log = LogFactory.getLog(DiskFeedInfoCache.class);
+    
+    private final String cachePath;
+    
+    
+    public DiskFeedInfoCache(String cp) {
+        if(cp.endsWith(File.separator)) {
+            // remove trailing slash
+            cachePath = cp.substring(0, cp.length() - 1);
+        } else {
+            cachePath = cp;
+        }
+        
+        log.debug("cache path = "+cachePath);
     }
-    public SyndFeedInfo getFeedInfo(URL url)
-    {
+    
+    
+    /**
+     * Get an item from the cache.
+     * 
+     * @param url The url for the feed.
+     * @return The cached SyndFeedInfo object, or null if feed has not been cached.
+     */
+    public SyndFeedInfo getFeedInfo(URL url) {
+        
         SyndFeedInfo info = null;
-        String fileName = cachePath + File.separator + "feed_" 
-                + Utilities.replaceNonAlphanumeric(url.toString(),'_').trim();        
-        FileInputStream fis;
-        try
-        {
+        
+        log.debug("CACHE GET - "+url.toString());
+        
+        FileInputStream fis = null;
+        try {
+            String fileName = getCacheFileName(url);
+            log.debug("CACHE FILE - "+fileName);
+            
             fis = new FileInputStream(fileName);
             ObjectInputStream ois = new ObjectInputStream(fis);
-            info = (SyndFeedInfo)ois.readObject();
-            fis.close();
+            info = (SyndFeedInfo) ois.readObject();
+        } catch (FileNotFoundException fnfe) {
+            // cache miss
+        } catch (Exception ex) {
+            // Error reading from cache
+            log.warn("Error reading from cache", ex);
+        } finally {
+            if(fis != null) try {
+                fis.close();
+            } catch (IOException ex) {
+                log.error("Error closing file stream", ex);
+            }
+        }
+        
+        if (info == null) {
+            log.debug("CACHE MISS - "+url.toString());
         }
-        catch (FileNotFoundException fnfe)
-        {
-            logger.debug("Cache miss for " + url.toString());
-        }
-        catch (ClassNotFoundException cnfe)
-        {
-            // Error writing to cahce is fatal
-            throw new RuntimeException("Attempting to read from cache", cnfe);
-        }
-        catch (IOException fnfe)
-        {
-            // Error writing to cahce is fatal
-            throw new RuntimeException("Attempting to read from cache", fnfe);
-        }
-        if (info == null) logger.debug("Cache MISS!");
+        
         return info;
     }
-
-    public void setFeedInfo(URL url, SyndFeedInfo feedInfo)
-    {
-        String fileName = cachePath + File.separator + "feed_" 
-                + Utilities.replaceNonAlphanumeric(url.toString(),'_').trim();  
-        FileOutputStream fos;
-        try
-        {
+    
+    
+    /**
+     * Put and item in the cache.
+     * 
+     * @param url The url for the feed.
+     * @param feedInfo The SyndFeedInfo object to cache.
+     */
+    public void setFeedInfo(URL url, SyndFeedInfo feedInfo) {
+        
+        log.debug("CACHE PUT - "+url.toString());
+        
+        FileOutputStream fos = null;
+        try {
+            String fileName = getCacheFileName(url);
+            log.debug("CACHE FILE - "+fileName);
+            
             fos = new FileOutputStream(fileName);
             ObjectOutputStream oos = new ObjectOutputStream(fos);
             oos.writeObject(feedInfo);
             fos.flush();
-            fos.close();
-        }
-        catch (Exception e)
-        {
-            // Error writing to cahce is fatal
-            throw new RuntimeException("Attempting to write to cache", e);
+        } catch (Exception ex) {
+            // Error writing to cache
+            log.warn("Error writing cache file", ex);
+        } finally {
+            if(fos != null) try {
+                fos.close();
+            } catch (IOException ex) {
+                log.error("Error closing output stream", ex);
+            }
         }
     }
+    
+    
+    /**
+     * Get the full file path to where we want our cached file to go for a 
+     * given url.  Since urls can be long we also want to make sure that the 
+     * final path is not more than 256 characters.
+     * 
+     * @param url The url to use for generating the file path.
+     * @return The file path to the cache file for the given url.
+     */
+    private String getCacheFileName(URL url) {
+        
+        String fileName = cachePath + File.separator;
+        
+        String fileSafeUrl = Utilities.replaceNonAlphanumeric(url.toString().trim(), '_');
+        if(fileSafeUrl.length() > 80) {
+            // url length is too long, lets shorten things a bit
+            log.debug("original fs safe filename - "+fileSafeUrl);
+            
+            String root = fileSafeUrl.substring(0, 80);
+            String extra = fileSafeUrl.substring(80);
+            
+            // hash extra data into base64
+            extra = Utilities.toBase64(extra.getBytes());
+            
+            // truncate it and hope this doesn't cause any collisions
+            int length = (extra.length() > 100) ? 100 : extra.length();
+            extra = extra.substring(0, length);
+            
+            fileSafeUrl = root + extra;
+        }
+        log.debug("fs safe filename - "+fileSafeUrl);
+        
+        fileName += "feed_" + fileSafeUrl;
+        
+        return fileName;
+    }
+    
 }

Added: roller/planet/core/trunk/test/conf/JPAEMF.properties
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/conf/JPAEMF.properties?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/test/conf/JPAEMF.properties (added)
+++ roller/planet/core/trunk/test/conf/JPAEMF.properties Sat Jun 28 12:18:17 2008
@@ -0,0 +1,26 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  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.  For additional information regarding
+# copyright in this work, please see the NOTICE file in the top level
+# directory of this distribution.
+
+# JPA properties file
+#
+# You can set JPA/Toplink, JPA/OpenJPA and JPA/Hibernate properties in your
+# roller-custom.properties override file. For other JPA implementations set
+# properties here and Roller will pick them up.
+
+# Required properties for using OpenJPA with Roller
+openjpa.IgnoreChanges=true
+openjpa.FlushBeforeQueries=true
+#openjpa.Log=DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE
\ No newline at end of file

Added: roller/planet/core/trunk/test/conf/commons-logging.properties
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/conf/commons-logging.properties?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/test/conf/commons-logging.properties (added)
+++ roller/planet/core/trunk/test/conf/commons-logging.properties Sat Jun 28 12:18:17 2008
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  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.  For additional information regarding
+# copyright in this work, please see the NOTICE file in the top level
+# directory of this distribution.
+
+org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.Log4jFactory
\ No newline at end of file

Added: roller/planet/core/trunk/test/conf/log4j.properties
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/conf/log4j.properties?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/test/conf/log4j.properties (added)
+++ roller/planet/core/trunk/test/conf/log4j.properties Sat Jun 28 12:18:17 2008
@@ -0,0 +1,44 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  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.  For additional information regarding
+# copyright in this work, please see the NOTICE file in the top level
+# directory of this distribution.
+
+# Properties for configuring Log4j for this application
+# This is the configuring for logging displayed in the Application Server
+log4j.rootCategory=INFO, roller
+
+log4j.appender.roller=org.apache.log4j.RollingFileAppender
+log4j.appender.roller.File=${catalina.base}/planet-test.log
+log4j.appender.roller.layout=org.apache.log4j.PatternLayout
+log4j.appender.roller.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss,SSS} %C{1}:%M - %m%n
+
+# Options are: DEBUG, INFO, WARN, ERROR, FATAL
+# Roller code
+log4j.category.org.apache.roller=INFO
+log4j.category.net.java.roller=INFO
+
+# Roller dependent libraries
+log4j.category.org.hibernate=INFO
+log4j.category.org.apache.struts=ERROR
+log4j.category.org.springframework=WARN
+log4j.category.org.acegisecurity=ERROR
+# Velocity talks a lot, so by default it is set to STFU mode
+log4j.category.org.apache.velocity=FATAL
+
+# Roller extras
+log4j.category.com.ecyrd.jspwiki=ERROR
+log4j.category.org.tuckey.web.filters.urlrewrite=DEBUG
+log4j.category.com.opensymphony.oscache=ERROR
+log4j.category.com.danga.MemCached=WARN
+

Added: roller/planet/core/trunk/test/conf/planet.properties
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/conf/planet.properties?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/test/conf/planet.properties (added)
+++ roller/planet/core/trunk/test/conf/planet.properties Sat Jun 28 12:18:17 2008
@@ -0,0 +1,18 @@
+
+# test email address, used for testing mailer functionality
+# put your own email address in here to get the email
+testEmail=root@localhost
+
+# Configure test database
+database.configurationType=jdbc
+database.jdbc.driverClass=com.mysql.jdbc.Driver
+database.jdbc.connectionURL=jdbc:mysql://localhost:3306/test_planet
+database.jdbc.username=roller
+database.jdbc.password=roller
+
+# Configure test mail server
+mail.configurationType=properties
+mail.hostname=mailhost
+#mail.port=
+#mail.username=
+#mail.password=

Modified: roller/planet/core/trunk/test/java/org/apache/roller/planet/TestUtils.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/java/org/apache/roller/planet/TestUtils.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/test/java/org/apache/roller/planet/TestUtils.java (original)
+++ roller/planet/core/trunk/test/java/org/apache/roller/planet/TestUtils.java Sat Jun 28 12:18:17 2008
@@ -18,13 +18,17 @@
 
 package org.apache.roller.planet;
 
-import org.apache.roller.planet.business.PlanetFactory;
+import org.apache.roller.planet.business.AggregatorFactory;
 import org.apache.roller.planet.business.PlanetManager;
+import org.apache.roller.planet.business.UserManager;
 import org.apache.roller.planet.business.startup.PlanetStartup;
+import org.apache.roller.planet.config.PlanetConfig;
 import org.apache.roller.planet.pojos.Planet;
 import org.apache.roller.planet.pojos.SubscriptionEntry;
 import org.apache.roller.planet.pojos.PlanetGroup;
+import org.apache.roller.planet.pojos.PlanetPermission;
 import org.apache.roller.planet.pojos.Subscription;
+import org.apache.roller.planet.pojos.User;
 
 
 /**
@@ -33,27 +37,30 @@
 public final class TestUtils {
     
     
-    public static void setupPlanet() throws Exception {
+    public static void setupAggregator() throws Exception {
         
-        if(!PlanetFactory.isBootstrapped()) {
+        if(!AggregatorFactory.isBootstrapped()) {
+            
+            // start with config
+            PlanetConfig config = PlanetConfig.getConfig(PlanetConfig.DEFAULT, PlanetConfig.CUSTOM, PlanetConfig.JVM_PARAM);
             
             // do core services preparation
-            PlanetStartup.prepare();
+            PlanetStartup.prepare(config);
             
             // do application bootstrapping and init
-            PlanetFactory.bootstrap();
+            AggregatorFactory.bootstrap(AggregatorFactory.getDefaultProvider(config));
             
             // always initialize the properties manager and flush
-            PlanetFactory.getPlanet().getPropertiesManager().initialize();
-            PlanetFactory.getPlanet().flush();
+            AggregatorFactory.getAggregator().getPropertiesManager().initialize();
+            AggregatorFactory.getAggregator().flush();
         }
     }
     
     
-    public static void shutdownPlanet() throws Exception {
+    public static void shutdownAggregator() throws Exception {
         
         // trigger shutdown
-        PlanetFactory.getPlanet().shutdown();
+        AggregatorFactory.getAggregator().shutdown();
     }
     
     
@@ -68,10 +75,57 @@
     public static void endSession(boolean flush) throws Exception {
         
         if(flush) {
-            PlanetFactory.getPlanet().flush();
+            AggregatorFactory.getAggregator().flush();
         }
         
-        PlanetFactory.getPlanet().release();
+        AggregatorFactory.getAggregator().release();
+    }
+    
+    
+    /**
+     * Convenience method that creates a user and stores it.
+     */
+    public static User setupUser(String username) throws Exception {
+        
+        User testUser = new User();
+        testUser.setUserName(username);
+        testUser.setPassword("password");
+        testUser.setFullName("Test User");
+        testUser.setEmailAddress("TestUser@dev.null");
+        testUser.setDateCreated(new java.util.Date());
+        testUser.setEnabled(Boolean.TRUE);
+        
+        // store the user
+        UserManager mgr = AggregatorFactory.getAggregator().getUserManager();
+        mgr.addUser(testUser);
+        
+        // flush to db
+        AggregatorFactory.getAggregator().flush();
+        
+        // query for the user to make sure we return the persisted object
+        User user = mgr.getUserByUserName(username);
+        
+        if(user == null)
+            throw new PlanetException("error inserting new user");
+        
+        return user;
+    }
+    
+    
+    /**
+     * Convenience method for removing a user.
+     */
+    public static void teardownUser(String id) throws Exception {
+        
+        // lookup the user
+        UserManager mgr = AggregatorFactory.getAggregator().getUserManager();
+        User user = mgr.getUser(id);
+        
+        // remove the user
+        mgr.removeUser(user);
+        
+        // flush to db
+        AggregatorFactory.getAggregator().flush();
     }
     
     
@@ -83,11 +137,11 @@
         Planet testPlanet = new Planet(handle, handle, handle);
         
         // store
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         mgr.savePlanet(testPlanet);
         
         // flush
-        PlanetFactory.getPlanet().flush();
+        AggregatorFactory.getAggregator().flush();
         
         // query to make sure we return the persisted object
         Planet planet = mgr.getPlanet(handle);
@@ -105,14 +159,60 @@
     public static void teardownPlanet(String id) throws Exception {
         
         // lookup
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         Planet planet = mgr.getPlanetById(id);
         
         // remove
         mgr.deletePlanet(planet);
         
         // flush
-        PlanetFactory.getPlanet().flush();
+        AggregatorFactory.getAggregator().flush();
+    }
+    
+    
+    /**
+     * Convenience method that creates a planet and stores it.
+     */
+    public static PlanetPermission setupPermissions(User user, Planet planet, short perms) throws Exception {
+        
+        PlanetPermission testPerm = new PlanetPermission();
+        testPerm.setUser(user);
+        testPerm.setPlanet(planet);
+        testPerm.setPending(false);
+        testPerm.setPermissionMask(perms);
+        
+        
+        // store
+        UserManager mgr = AggregatorFactory.getAggregator().getUserManager();
+        mgr.savePermissions(testPerm);
+        
+        // flush
+        AggregatorFactory.getAggregator().flush();
+        
+        // query to make sure we return the persisted object
+        PlanetPermission perm = mgr.getPermissions(testPerm.getId());
+        
+        if(perm == null)
+            throw new PlanetException("error inserting new planet permissions");
+        
+        return perm;
+    }
+    
+    
+    /**
+     * Convenience method for removing a permission.
+     */
+    public static void teardownPermissions(String id) throws Exception {
+        
+        // lookup the permissions
+        UserManager mgr = AggregatorFactory.getAggregator().getUserManager();
+        PlanetPermission perm = mgr.getPermissions(id);
+        
+        // remove the permissions
+        mgr.removePermissions(perm);
+        
+        // flush to db
+        AggregatorFactory.getAggregator().flush();
     }
     
     
@@ -122,7 +222,7 @@
     public static PlanetGroup setupGroup(Planet planet, String handle) 
             throws Exception {
         
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         
         // make sure we are using a persistent object
         Planet testPlanet = mgr.getPlanetById(planet.getId());
@@ -133,7 +233,7 @@
         mgr.saveGroup(testGroup);
         
         // flush
-        PlanetFactory.getPlanet().flush();
+        AggregatorFactory.getAggregator().flush();
         
         // query to make sure we return the persisted object
         PlanetGroup group = mgr.getGroupById(testGroup.getId());
@@ -151,7 +251,7 @@
     public static void teardownGroup(String id) throws Exception {
         
         // lookup
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         PlanetGroup group = mgr.getGroupById(id);
         
         // remove
@@ -159,7 +259,7 @@
         group.getPlanet().getGroups().remove(group);
         
         // flush
-        PlanetFactory.getPlanet().flush();
+        AggregatorFactory.getAggregator().flush();
     }
     
     
@@ -169,7 +269,7 @@
     public static Subscription setupSubscription(String feedUrl) 
             throws Exception {
         
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         
         // store
         Subscription testSub = new Subscription();
@@ -178,7 +278,7 @@
         mgr.saveSubscription(testSub);
         
         // flush
-        PlanetFactory.getPlanet().flush();
+        AggregatorFactory.getAggregator().flush();
         
         // query to make sure we return the persisted object
         Subscription sub = mgr.getSubscriptionById(testSub.getId());
@@ -196,14 +296,14 @@
     public static void teardownSubscription(String id) throws Exception {
         
         // lookup
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         Subscription sub = mgr.getSubscriptionById(id);
         
         // remove
         mgr.deleteSubscription(sub);
         
         // flush
-        PlanetFactory.getPlanet().flush();
+        AggregatorFactory.getAggregator().flush();
     }
     
     
@@ -213,7 +313,7 @@
     public static SubscriptionEntry setupEntry(Subscription sub, String title) 
             throws Exception {
         
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         
         // make sure we are using a persistent object
         Subscription testSub = mgr.getSubscriptionById(sub.getId());
@@ -228,7 +328,7 @@
         mgr.saveEntry(testEntry);
         
         // flush
-        PlanetFactory.getPlanet().flush();
+        AggregatorFactory.getAggregator().flush();
         
         // query to make sure we return the persisted object
         SubscriptionEntry entry = mgr.getEntryById(testEntry.getId());
@@ -246,7 +346,7 @@
     public static void teardownEntry(String id) throws Exception {
         
         // lookup
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         SubscriptionEntry entry = mgr.getEntryById(id);
         
         // remove
@@ -254,7 +354,40 @@
         entry.getSubscription().getEntries().remove(entry);
         
         // flush
-        PlanetFactory.getPlanet().flush();
+        AggregatorFactory.getAggregator().flush();
+    }
+    
+    
+    /**
+     * Convenience method that returns managed copy of given user.
+     */
+    public static User getManagedUser(User user) throws PlanetException {
+        UserManager mgr = AggregatorFactory.getAggregator().getUserManager();
+        return mgr.getUser(user.getId());
+    }
+    
+    /**
+     * Convenience method that returns managed copy of given planet.
+     */
+    public static Planet getManagedPlanet(Planet planet) throws PlanetException {
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
+        return mgr.getPlanetById(planet.getId());
+    }
+    
+    /**
+     * Convenience method that returns managed copy of given group.
+     */
+    public static PlanetGroup getManagedGroup(PlanetGroup group) throws PlanetException {
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
+        return mgr.getGroupById(group.getId());
+    }
+    
+    /**
+     * Convenience method that returns managed copy of given subscription.
+     */
+    public static Subscription getManagedSubscription(Subscription sub) throws PlanetException {
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
+        return mgr.getSubscriptionById(sub.getId());
     }
     
 }

Added: roller/planet/core/trunk/test/java/org/apache/roller/planet/business/AbstractBusinessTestCase.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/java/org/apache/roller/planet/business/AbstractBusinessTestCase.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/test/java/org/apache/roller/planet/business/AbstractBusinessTestCase.java (added)
+++ roller/planet/core/trunk/test/java/org/apache/roller/planet/business/AbstractBusinessTestCase.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,42 @@
+
+package org.apache.roller.planet.business;
+
+import junit.framework.TestCase;
+import org.apache.roller.planet.TestUtils;
+
+
+/**
+ * Abstract class providing basic startup and teardown needed for all business
+ * layer tests.
+ *
+ * @author ag92114
+ */
+public abstract class AbstractBusinessTestCase extends TestCase {
+    
+    public AbstractBusinessTestCase() {
+        super();
+    }
+    
+    public AbstractBusinessTestCase(String name) {
+        super(name);
+    }
+    
+    
+    @Override
+    public void setUp() throws Exception {
+        // setup planet
+        TestUtils.setupAggregator();
+    }
+    
+    @Override
+    public void tearDown() throws Exception {
+        // shutdown planet
+        TestUtils.shutdownAggregator();
+    }
+
+    public void endSession(boolean flush) throws Exception {
+        // close persistence session
+        TestUtils.endSession(flush);
+    }
+    
+}

Added: roller/planet/core/trunk/test/java/org/apache/roller/planet/business/DatabaseProviderTest.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/java/org/apache/roller/planet/business/DatabaseProviderTest.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/test/java/org/apache/roller/planet/business/DatabaseProviderTest.java (added)
+++ roller/planet/core/trunk/test/java/org/apache/roller/planet/business/DatabaseProviderTest.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,46 @@
+
+package org.apache.roller.planet.business;
+
+import java.sql.Connection;
+import org.apache.roller.planet.config.PlanetConfig;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+/**
+ * Unit test of DatabaseProvider class.
+ *
+ * @author ag92114
+ */
+public class DatabaseProviderTest {
+    
+    private PlanetConfig config = null;
+    
+    
+    @Before
+    public void setUp() {
+        config = PlanetConfig.getConfig(PlanetConfig.DEFAULT, PlanetConfig.CUSTOM, PlanetConfig.JVM_PARAM);
+    }
+
+    @After
+    public void tearDown() {
+        config = null;
+    }
+    
+
+    /**
+     * Test of getConnection method (using jdbc props), of class DatabaseProvider.
+     */
+    @Test
+    public void getConnectionViaJdbcProperties() throws Exception {
+        System.out.println("getConnectionViaJdbcProperties");
+        
+        DatabaseProvider instance = new DatabaseProvider(config);
+        
+        Connection con = instance.getConnection();
+        assertNotNull(con);
+    }
+
+}

Modified: roller/planet/core/trunk/test/java/org/apache/roller/planet/business/EntryBasicTests.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/java/org/apache/roller/planet/business/EntryBasicTests.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/test/java/org/apache/roller/planet/business/EntryBasicTests.java (original)
+++ roller/planet/core/trunk/test/java/org/apache/roller/planet/business/EntryBasicTests.java Sat Jun 28 12:18:17 2008
@@ -16,8 +16,6 @@
 
 package org.apache.roller.planet.business;
 
-import java.util.Date;
-import junit.framework.TestCase;
 import org.apache.roller.planet.TestUtils;
 import org.apache.roller.planet.pojos.SubscriptionEntry;
 import org.apache.roller.planet.pojos.Subscription;
@@ -26,27 +24,30 @@
 /**
  * Test Entry CRUD.
  */
-public class EntryBasicTests extends TestCase {
+public class EntryBasicTests extends AbstractBusinessTestCase {
     
     private Subscription testSub = null;
     
     
-    protected void setUp() throws Exception {
-        // setup planet
-        TestUtils.setupPlanet();
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
         
         testSub = TestUtils.setupSubscription("entryBasicTest");
     }
     
     
-    protected void tearDown() throws Exception {
+    @Override
+    public void tearDown() throws Exception {
         TestUtils.teardownSubscription(testSub.getId());
+        
+        super.tearDown();
     }
     
     
     public void testEntryCRUD() throws Exception {
         
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         Subscription sub = mgr.getSubscriptionById(testSub.getId());
         
         SubscriptionEntry testEntry = new SubscriptionEntry();
@@ -57,7 +58,7 @@
         
         // add
         mgr.saveEntry(testEntry);
-        TestUtils.endSession(true);
+        endSession(true);
         
         // verify
         SubscriptionEntry entry = null;
@@ -68,7 +69,7 @@
         // modify
         entry.setTitle("foo");
         mgr.saveEntry(entry);
-        TestUtils.endSession(true);
+        endSession(true);
         
         // verify
         entry = null;
@@ -78,7 +79,7 @@
         
         // remove
         mgr.deleteEntry(entry);
-        TestUtils.endSession(true);
+        endSession(true);
         
         // verify
         entry = null;

Modified: roller/planet/core/trunk/test/java/org/apache/roller/planet/business/EntryFunctionalTests.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/java/org/apache/roller/planet/business/EntryFunctionalTests.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/test/java/org/apache/roller/planet/business/EntryFunctionalTests.java (original)
+++ roller/planet/core/trunk/test/java/org/apache/roller/planet/business/EntryFunctionalTests.java Sat Jun 28 12:18:17 2008
@@ -17,7 +17,6 @@
 package org.apache.roller.planet.business;
 
 import java.util.Date;
-import junit.framework.TestCase;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.planet.TestUtils;
@@ -30,7 +29,7 @@
 /**
  * Test planet Entry functionality.
  */
-public class EntryFunctionalTests extends TestCase {
+public class EntryFunctionalTests extends AbstractBusinessTestCase {
     
     public static Log log = LogFactory.getLog(EntryFunctionalTests.class);
     
@@ -43,9 +42,9 @@
     private SubscriptionEntry testEntry3 = null;
     
     
-    protected void setUp() throws Exception {
-        // setup planet
-        TestUtils.setupPlanet();
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
 
         log.info("ENTERED");
         
@@ -64,14 +63,15 @@
         testGroup1.getSubscriptions().add(testSub2);
         testSub2.getGroups().add(testGroup1);
         
-        PlanetFactory.getPlanet().getPlanetManager().saveGroup(testGroup1);
-        PlanetFactory.getPlanet().flush();
+        AggregatorFactory.getAggregator().getPlanetManager().saveGroup(testGroup1);
+        AggregatorFactory.getAggregator().flush();
         
         log.info("EXITED");
     }
     
     
-    protected void tearDown() throws Exception {
+    @Override
+    public void tearDown() throws Exception {
         log.info("ENTERED");
         
         TestUtils.teardownSubscription(testSub1.getId());
@@ -80,12 +80,14 @@
         TestUtils.teardownPlanet(testPlanet.getId());
         
         log.info("EXITED");
+        
+        super.tearDown();
     }
     
     
     public void testEntryLookups() throws Exception {
         
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         
         // by id
         SubscriptionEntry entry = mgr.getEntryById(testEntry1.getId());
@@ -110,7 +112,7 @@
     
     public void testDeleteEntries() throws Exception {
         
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         Subscription sub = mgr.getSubscriptionById(testSub2.getId());
         
         // make sure entries are there
@@ -118,7 +120,7 @@
         
         // purge entries
         mgr.deleteEntries(sub);
-        TestUtils.endSession(true);
+        endSession(true);
         
         // verify
         sub = mgr.getSubscriptionById(testSub2.getId());

Modified: roller/planet/core/trunk/test/java/org/apache/roller/planet/business/GroupBasicTests.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/java/org/apache/roller/planet/business/GroupBasicTests.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/test/java/org/apache/roller/planet/business/GroupBasicTests.java (original)
+++ roller/planet/core/trunk/test/java/org/apache/roller/planet/business/GroupBasicTests.java Sat Jun 28 12:18:17 2008
@@ -16,8 +16,6 @@
 
 package org.apache.roller.planet.business;
 
-import java.util.List;
-import junit.framework.TestCase;
 import org.apache.roller.planet.TestUtils;
 import org.apache.roller.planet.pojos.Planet;
 import org.apache.roller.planet.pojos.PlanetGroup;
@@ -26,27 +24,30 @@
 /**
  * Test Group CRUD.
  */
-public class GroupBasicTests extends TestCase {
+public class GroupBasicTests extends AbstractBusinessTestCase {
     
     private Planet testPlanet = null;
     
     
-    protected void setUp() throws Exception {
-        // setup planet
-        TestUtils.setupPlanet();
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
 
         testPlanet = TestUtils.setupPlanet("groupBasicTest");
     }
     
     
-    protected void tearDown() throws Exception {
+    @Override
+    public void tearDown() throws Exception {
         TestUtils.teardownPlanet(testPlanet.getId());
+        
+        super.tearDown();
     }
     
     
     public void testGroupCRUD() throws Exception {
         
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         
         PlanetGroup testGroup = new PlanetGroup();
         testGroup.setDescription("test_group_desc");
@@ -60,7 +61,7 @@
         
         // add
         mgr.saveGroup(testGroup);
-        TestUtils.endSession(true);
+        endSession(true);
         
         // verify
         group = null;
@@ -72,7 +73,7 @@
         // modify
         group.setTitle("foo");
         mgr.saveGroup(group);
-        TestUtils.endSession(true);
+        endSession(true);
         
         // verify
         group = null;
@@ -82,7 +83,7 @@
         
         // remove
         mgr.deleteGroup(group);
-        TestUtils.endSession(true);
+        endSession(true);
         
         // verify
         group = null;

Modified: roller/planet/core/trunk/test/java/org/apache/roller/planet/business/GroupFunctionalTests.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/java/org/apache/roller/planet/business/GroupFunctionalTests.java?rev=672574&r1=672573&r2=672574&view=diff
==============================================================================
--- roller/planet/core/trunk/test/java/org/apache/roller/planet/business/GroupFunctionalTests.java (original)
+++ roller/planet/core/trunk/test/java/org/apache/roller/planet/business/GroupFunctionalTests.java Sat Jun 28 12:18:17 2008
@@ -17,7 +17,6 @@
 package org.apache.roller.planet.business;
 
 import java.util.Set;
-import junit.framework.TestCase;
 import org.apache.roller.planet.TestUtils;
 import org.apache.roller.planet.pojos.Planet;
 import org.apache.roller.planet.pojos.PlanetGroup;
@@ -26,16 +25,16 @@
 /**
  * Test planet Group functionality.
  */
-public class GroupFunctionalTests extends TestCase {
+public class GroupFunctionalTests extends AbstractBusinessTestCase {
     
     private Planet testPlanet = null;
     private PlanetGroup testGroup1 = null;
     private PlanetGroup testGroup2 = null;
     
     
-    protected void setUp() throws Exception {
-        // setup planet
-        TestUtils.setupPlanet();
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
 
         testPlanet = TestUtils.setupPlanet("groupFuncTest");
         testGroup1 = TestUtils.setupGroup(testPlanet, "groupFuncTest1");
@@ -43,16 +42,19 @@
     }
     
     
-    protected void tearDown() throws Exception {
+    @Override
+    public void tearDown() throws Exception {
         TestUtils.teardownGroup(testGroup1.getId());
         TestUtils.teardownGroup(testGroup2.getId());
         TestUtils.teardownPlanet(testPlanet.getId());
+        
+        super.tearDown();
     }
     
     
     public void testGroupLookups() throws Exception {
         
-        PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager();
+        PlanetManager mgr = AggregatorFactory.getAggregator().getPlanetManager();
         
         // lookup group by id
         PlanetGroup group = mgr.getGroupById(testGroup1.getId());

Added: roller/planet/core/trunk/test/java/org/apache/roller/planet/business/MailProviderTest.java
URL: http://svn.apache.org/viewvc/roller/planet/core/trunk/test/java/org/apache/roller/planet/business/MailProviderTest.java?rev=672574&view=auto
==============================================================================
--- roller/planet/core/trunk/test/java/org/apache/roller/planet/business/MailProviderTest.java (added)
+++ roller/planet/core/trunk/test/java/org/apache/roller/planet/business/MailProviderTest.java Sat Jun 28 12:18:17 2008
@@ -0,0 +1,102 @@
+
+package org.apache.roller.planet.business;
+
+import java.util.Properties;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import org.apache.roller.planet.config.PlanetConfig;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+/**
+ * Unit test of MailProvider class.
+ *
+ * @author ag92114
+ */
+public class MailProviderTest {
+
+    private PlanetConfig config = null;
+    
+    
+    @Before
+    public void setUp() {
+        config = PlanetConfig.getConfig(PlanetConfig.DEFAULT, PlanetConfig.CUSTOM, PlanetConfig.JVM_PARAM);
+    }
+
+    @After
+    public void tearDown() {
+        config = null;
+    }
+    
+
+    /**
+     * Test of getSession method (using jdbc props), of class DatabaseProvider.
+     */
+    @Test
+    public void getSessionViaJdbcProperties() throws Exception {
+        System.out.println("getSessionViaJdbcProperties");
+        
+        MailProvider instance = new MailProvider(config);
+        
+        Session session = instance.getSession();
+        if(session != null) {
+            Transport transport = null;
+            try {
+                transport = session.getTransport();
+                transport.connect();
+            } catch(Exception ex) {
+                fail("Transport failed to connect: "+ex.getMessage());
+            } finally {
+                if(transport != null) {
+                    transport.close();
+                }
+            }
+        } else {
+            fail("MailProvider Session was null.");
+        }
+    }
+    
+    
+    /**
+     * Test of getSession method (using jndi), of class DatabaseProvider.
+     */
+//    @Test
+//    public void getSessionViaJndi() throws Exception {
+//        System.out.println("getSessionViaJndi");
+//        
+//        // get config as usual, then put it into a temporary jndi context
+//        // so that we can try creating a MailProvider from jndi
+//        MailProvider tmpProvider = new MailProvider(config);
+//        
+//        Context ctx = (Context) new InitialContext(null);
+//        ctx.bind("java:comp/env/mail/Session", tmpProvider.getSession());
+//        
+//        Properties props = new Properties();
+//        props.put("mail.configurationType", "jndi");
+//        props.put("mail.jndi.name", "java:comp/env/mail/Session");
+//        MailProvider instance = new MailProvider(new PlanetConfig(props, null));
+//        
+//        Session session = instance.getSession();
+//        if(session != null) {
+//            Transport transport = null;
+//            try {
+//                transport = session.getTransport();
+//                transport.connect();
+//            } catch(Exception ex) {
+//                fail("Transport failed to connect: "+ex.getMessage());
+//            } finally {
+//                if(transport != null) {
+//                    transport.close();
+//                }
+//            }
+//        } else {
+//            fail("MailProvider Session was null.");
+//        }
+//    }
+    
+}