You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2005/10/21 23:46:28 UTC
svn commit: r327589 [18/72] - in /incubator/roller/branches/roller_1.x: ./
contrib/ contrib/lib/ contrib/plugins/ contrib/plugins/src/
contrib/plugins/src/org/ contrib/plugins/src/org/roller/
contrib/plugins/src/org/roller/presentation/ contrib/plugins...
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/HitCountData.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/HitCountData.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/HitCountData.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/HitCountData.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,167 @@
+package org.roller.business;
+
+/**
+ * Hit count bean.
+ * @author David M Johnson
+ *
+ * @castor:class name="HitCount" table="referer" id="id" key-generator="UUID"
+ * @hibernate.class table="referer"
+ */
+public class HitCountData
+ extends org.roller.pojos.PersistentObject
+ implements java.io.Serializable
+{
+ static final long serialVersionUID = -7998453141931097201L;
+
+ protected java.lang.String id;
+ protected java.lang.Integer dayHitCount;
+ protected java.lang.Integer totalHitCount;
+ protected org.roller.pojos.WebsiteData website;
+
+ public HitCountData()
+ {
+ }
+
+ public HitCountData( java.lang.String id,
+ java.lang.Integer dayHitCount, java.lang.Integer totalHitCount )
+ {
+ this.id = id;
+ this.totalHitCount = totalHitCount;
+ this.dayHitCount = dayHitCount;
+ }
+
+ public HitCountData( HitCountData otherData )
+ {
+ this.id = otherData.id;
+ this.totalHitCount = otherData.totalHitCount;
+ this.dayHitCount = otherData.dayHitCount;
+ }
+
+ /** @castor:field set-method="setId"
+ * @castor:field-sql name="id" sql-dirty="check" dirty="check"
+ * @castor:field-xml node="attribute"
+ * @hibernate.id column="id" type="string"
+ * generator-class="uuid.hex" unsaved-value="null"
+ */
+ public java.lang.String getId()
+ {
+ return this.id;
+ }
+ public void setId( java.lang.String id )
+ {
+ this.id = id;
+ }
+
+ /** Day hit count.
+ * @castor:field set-method="setDayHitCount"
+ * @castor:field-sql name="dayhits" sql-dirty="check" dirty="check"
+ * @hibernate.property column="dayhits" non-null="true" unique="false"
+ */
+ public java.lang.Integer getDayHitCount()
+ {
+ return this.dayHitCount;
+ }
+ public void setDayHitCount( java.lang.Integer dayHitCount )
+ {
+ this.dayHitCount = dayHitCount;
+ }
+
+ /** Total hit count.
+ * @castor:field set-method="setTotalHitCount"
+ * @castor:field-sql name="totalhits" sql-dirty="check" dirty="check"
+ * @hibernate.property column="totalhits" non-null="true" unique="false"
+ */
+ public java.lang.Integer getTotalHitCount()
+ {
+ return this.totalHitCount;
+ }
+ public void setTotalHitCount( java.lang.Integer hitCount )
+ {
+ this.totalHitCount = hitCount;
+ }
+
+ /**
+ * ID of website that this referer refers to.
+ * @hibernate.many-to-one column="websiteid" cascade="none" not-null="true"
+ */
+ public org.roller.pojos.WebsiteData getWebsite()
+ {
+ return this.website;
+ }
+ public void setWebsite( org.roller.pojos.WebsiteData website )
+ {
+ this.website = website;
+ }
+
+ public String toString()
+ {
+ StringBuffer str = new StringBuffer("{");
+
+ str.append("id=" + id + " " + "dayHitCount=" + dayHitCount);
+ str.append('}');
+
+ return(str.toString());
+ }
+
+ public boolean equals( Object pOther )
+ {
+ if( pOther instanceof HitCountData )
+ {
+ HitCountData lTest = (HitCountData) pOther;
+ boolean lEquals = true;
+
+ if( this.id == null )
+ {
+ lEquals = lEquals && ( lTest.id == null );
+ }
+ else
+ {
+ lEquals = lEquals && this.id.equals( lTest.id );
+ }
+ if( this.dayHitCount == null )
+ {
+ lEquals = lEquals && ( lTest.dayHitCount == null );
+ }
+ else
+ {
+ lEquals = lEquals && this.dayHitCount.equals( lTest.dayHitCount );
+ }
+ if( this.totalHitCount == null )
+ {
+ lEquals = lEquals && ( lTest.totalHitCount == null );
+ }
+ else
+ {
+ lEquals= lEquals && this.totalHitCount.equals(lTest.totalHitCount);
+ }
+
+ return lEquals;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public int hashCode()
+ {
+ int result = 17;
+ result = 37*result + ((this.id != null) ? this.id.hashCode() : 0);
+ result = 37*result + ((this.dayHitCount != null) ? this.dayHitCount.hashCode() : 0);
+ result = 37*result + ((this.totalHitCount != null) ? this.totalHitCount.hashCode() : 0);
+ return result;
+ }
+
+ /**
+ * Setter is needed in RollerImpl.storePersistentObject()
+ */
+ public void setData( org.roller.pojos.PersistentObject otherData )
+ {
+
+ this.id = ((HitCountData)otherData).id;
+
+ this.dayHitCount = ((HitCountData)otherData).dayHitCount;
+ this.totalHitCount = ((HitCountData)otherData).totalHitCount;
+ }
+
+}
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/IndexManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/IndexManagerImpl.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/IndexManagerImpl.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/IndexManagerImpl.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,431 @@
+/*
+ * Created on Jul 18, 2003
+ *
+ * Authored by: Mindaugas Idzelis (min@idzelis.com)
+ */
+package org.roller.business;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.lucene.store.RAMDirectory;
+import org.roller.RollerException;
+import org.roller.business.search.operations.AddEntryOperation;
+import org.roller.business.search.operations.IndexOperation;
+import org.roller.business.search.operations.ReIndexEntryOperation;
+import org.roller.business.search.operations.RebuildUserIndexOperation;
+import org.roller.business.search.operations.RemoveEntryOperation;
+import org.roller.business.search.operations.RemoveUserIndexOperation;
+import org.roller.business.search.operations.WriteToIndexOperation;
+import org.roller.model.IndexManager;
+import org.roller.pojos.UserData;
+import org.roller.pojos.WeblogEntryData;
+
+import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
+import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock;
+import org.roller.config.RollerConfig;
+import org.roller.model.RollerFactory;
+import org.roller.util.StringUtils;
+
+/**
+ * Lucene implementation of IndexManager. This is the central entry point into the Lucene
+ * searching API.
+ * @author aim4min
+ * @author mraible (formatting and making indexDir configurable)
+ */
+public class IndexManagerImpl implements IndexManager
+{
+ //~ Static fields/initializers
+ // =============================================
+
+ private IndexReader reader;
+
+ static Log mLogger = LogFactory.getFactory().getInstance(
+ IndexManagerImpl.class);
+
+ //~ Instance fields
+ // ========================================================
+
+ private boolean searchEnabled = true;
+
+ File indexConsistencyMarker;
+
+ private boolean useRAMIndex = false;
+
+ private RAMDirectory fRAMindex;
+
+ private String indexDir = null;
+
+ private boolean inconsistentAtStartup = false;
+
+ private ReadWriteLock rwl = new WriterPreferenceReadWriteLock();
+
+ //~ Constructors
+ // ===========================================================
+
+ /**
+ * Creates a new lucene index manager. This should only be created once.
+ * Creating the index manager more than once will definately result in
+ * errors. The prefered way of getting an index is through the
+ * RollerContext.
+ *
+ * @param indexDir -
+ * the path to the index directory
+ */
+ public IndexManagerImpl()
+ {
+ // check config to see if the internal search is enabled
+ String enabled = RollerConfig.getProperty("search.enabled");
+ if("false".equalsIgnoreCase(enabled))
+ this.searchEnabled = false;
+
+ // we also need to know what our index directory is
+ // Note: system property expansion is now handled by RollerConfig
+ String indexDir = RollerConfig.getProperty("search.index.dir");
+
+ this.indexDir = indexDir.replace('/', File.separatorChar);
+
+ // a little debugging
+ mLogger.info("search enabled: " + this.searchEnabled);
+ mLogger.info("index dir: " + this.indexDir);
+
+ String test = indexDir + File.separator + ".index-inconsistent";
+ indexConsistencyMarker = new File(test);
+
+ // only setup the index if search is enabled
+ if (this.searchEnabled)
+ {
+
+ // 1. If inconsistency marker exists.
+ // Delete index
+ // 2. if we're using RAM index
+ // load ram index wrapper around index
+ //
+ if (indexConsistencyMarker.exists())
+ {
+ getFSDirectory(true);
+ inconsistentAtStartup = true;
+ }
+ else
+ {
+ try
+ {
+ File makeIndexDir = new File(indexDir);
+ if (!makeIndexDir.exists())
+ {
+ makeIndexDir.mkdirs();
+ inconsistentAtStartup = true;
+ }
+ indexConsistencyMarker.createNewFile();
+ }
+ catch (IOException e)
+ {
+ mLogger.error(e);
+ }
+ }
+
+ if (indexExists())
+ {
+ if (useRAMIndex)
+ {
+ Directory filesystem = getFSDirectory(false);
+
+ try
+ {
+ fRAMindex = new RAMDirectory(filesystem);
+ }
+ catch (IOException e)
+ {
+ mLogger.error("Error creating in-memory index", e);
+ }
+ }
+ }
+ else
+ {
+ if (useRAMIndex)
+ {
+ fRAMindex = new RAMDirectory();
+ createIndex(fRAMindex);
+ }
+ else
+ {
+ createIndex(getFSDirectory(true));
+ }
+ }
+
+ if (isInconsistentAtStartup())
+ {
+ mLogger.info(
+ "Index was inconsistent. Rebuilding index in the background...");
+ try
+ {
+ rebuildUserIndex();
+ }
+ catch (RollerException e)
+ {
+ mLogger.error("ERROR: scheduling re-index operation");
+ }
+ }
+ }
+ }
+
+ //~ Methods
+ // ================================================================
+
+ public void rebuildUserIndex() throws RollerException
+ {
+ scheduleIndexOperation(
+ new RebuildUserIndexOperation(this, null));
+ }
+
+ public void removeUserIndex(UserData user) throws RollerException
+ {
+ scheduleIndexOperation(
+ new RemoveUserIndexOperation(this, user));
+ }
+
+ public void addEntryIndexOperation(WeblogEntryData entry) throws RollerException
+ {
+ AddEntryOperation addEntry = new AddEntryOperation(this, entry);
+ scheduleIndexOperation(addEntry);
+ }
+
+ public void addEntryReIndexOperation(WeblogEntryData entry) throws RollerException
+ {
+ ReIndexEntryOperation reindex = new ReIndexEntryOperation(this, entry);
+ scheduleIndexOperation(reindex);
+ }
+
+ public void removeEntryIndexOperation(WeblogEntryData entry) throws RollerException
+ {
+ RemoveEntryOperation removeOp = new RemoveEntryOperation(this, entry);
+ executeIndexOperationNow(removeOp);
+ }
+
+ public ReadWriteLock getReadWriteLock()
+ {
+ return rwl;
+ }
+
+ public boolean isInconsistentAtStartup()
+ {
+ return inconsistentAtStartup;
+ }
+
+ /**
+ * This is the analyzer that will be used to tokenize comment text.
+ *
+ * @return Analyzer to be used in manipulating the database.
+ */
+ public static final Analyzer getAnalyzer()
+ {
+ return new StandardAnalyzer();
+ }
+
+ private void scheduleIndexOperation(final IndexOperation op)
+ {
+ try
+ {
+ // only if search is enabled
+ if(this.searchEnabled) {
+ mLogger.debug("Starting scheduled index operation: "+op.getClass().getName());
+ RollerFactory.getRoller().getThreadManager().executeInBackground(op);
+ }
+ }
+ catch (RollerException re)
+ {
+ mLogger.error("Error getting thread manager", re);
+ }
+ catch (InterruptedException e)
+ {
+ mLogger.error("Error executing operation", e);
+ }
+ }
+
+ /**
+ * @param search
+ */
+ public void executeIndexOperationNow(final IndexOperation op)
+ {
+ try
+ {
+ // only if search is enabled
+ if(this.searchEnabled) {
+ mLogger.debug("Executing index operation now: "+op.getClass().getName());
+ RollerFactory.getRoller().getThreadManager().executeInForeground(op);
+ }
+ }
+ catch (RollerException re)
+ {
+ mLogger.error("Error getting thread manager", re);
+ }
+ catch (InterruptedException e)
+ {
+ mLogger.error("Error executing operation", e);
+ }
+ }
+
+ public synchronized void resetSharedReader()
+ {
+ reader = null;
+ }
+ public synchronized IndexReader getSharedIndexReader()
+ {
+ if (reader == null)
+ {
+ try
+ {
+ reader = IndexReader.open(getIndexDirectory());
+ }
+ catch (IOException e)
+ {
+ }
+ }
+ return reader;
+ }
+
+ /**
+ * Get the directory that is used by the lucene index. This method will
+ * return null if there is no index at the directory location. If we are
+ * using a RAM index, the directory will be a ram directory.
+ *
+ * @return Directory The directory containing the index, or null if error.
+ */
+ public Directory getIndexDirectory()
+ {
+ if (useRAMIndex)
+ {
+ return fRAMindex;
+ }
+ else
+ {
+ return getFSDirectory(false);
+ }
+ }
+
+ private boolean indexExists()
+ {
+ return IndexReader.indexExists(indexDir);
+ }
+
+ Directory getFSDirectory(boolean delete)
+ {
+ Directory directory = null;
+
+ try
+ {
+ directory = FSDirectory.getDirectory(indexDir, delete);
+ }
+ catch (IOException e)
+ {
+ mLogger.error("Problem accessing index directory", e);
+ }
+
+ return directory;
+ }
+
+ private void createIndex(Directory dir)
+ {
+ IndexWriter writer = null;
+
+ try
+ {
+ writer = new IndexWriter(dir, IndexManagerImpl.getAnalyzer(), true);
+ }
+ catch (IOException e)
+ {
+ mLogger.error("Error creating index", e);
+ }
+ finally
+ {
+ try
+ {
+ if (writer != null)
+ {
+ writer.close();
+ }
+ }
+ catch (IOException e)
+ {
+ }
+ }
+ }
+
+ private IndexOperation getSaveIndexOperation()
+ {
+ return new WriteToIndexOperation(this) {
+ public void doRun()
+ {
+ Directory dir = getIndexDirectory();
+ Directory fsdir = getFSDirectory(true);
+
+ IndexWriter writer = null;
+
+ try
+ {
+ writer = new IndexWriter(fsdir, IndexManagerImpl
+ .getAnalyzer(), true);
+
+ writer.addIndexes(new Directory[] { dir });
+ indexConsistencyMarker.delete();
+ }
+ catch (IOException e)
+ {
+ mLogger.error("Problem saving index to disk", e);
+
+ // Delete the directory, since there was a problem saving
+ // the RAM contents
+ getFSDirectory(true);
+ }
+ finally
+ {
+ try
+ {
+ if (writer != null)
+ writer.close();
+ }
+ catch (IOException e1)
+ {
+ mLogger.warn("Unable to close IndexWriter.");
+ }
+ }
+
+ }
+ };
+ }
+
+ public void release()
+ {
+ // no-op
+ }
+
+ public void shutdown()
+ {
+ if (useRAMIndex)
+ {
+ scheduleIndexOperation(getSaveIndexOperation());
+ }
+ else
+ {
+ indexConsistencyMarker.delete();
+ }
+
+ try
+ {
+ if (reader != null)
+ reader.close();
+ }
+ catch (IOException e)
+ {
+ // won't happen, since it was
+ }
+ }
+}
\ No newline at end of file
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/PersistenceStrategy.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/PersistenceStrategy.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/PersistenceStrategy.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/PersistenceStrategy.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,76 @@
+/*
+ * Created on Aug 13, 2003
+ */
+package org.roller.business;
+
+import java.io.Serializable;
+
+import org.roller.RollerException;
+import org.roller.pojos.PersistentObject;
+import org.roller.pojos.UserData;
+
+/**
+ * Persistence strategy masks underlying persistence mechanism.
+ * State is held in thread local storage (TLS).
+ * When you call begin(), a PersistenceSession object is associated with your thread.
+ * When you call release(), TLS is cleared.
+ *
+ * @author Lance Lavandowska
+ * @author Dave Johnson
+ */
+public interface PersistenceStrategy extends Serializable
+{
+ /**
+ * Save a persistent object to storage. This method is only needed when
+ * a new object is to be added to storage.
+ */
+ public PersistentObject store(PersistentObject data)
+ throws RollerException;
+
+ /**
+ * Load an persistent object from storage. Object returned is a
+ * persistent instance, meaning that changes to it will be automatically
+ * saved to storage the next time that commit() is called.
+ */
+ public PersistentObject load(
+ String id, Class cls) throws RollerException;
+
+ /**
+ * Remove an object from storage.
+ */
+ public void remove(PersistentObject po)
+ throws RollerException;
+
+ /**
+ * Remove an object from storage.
+ */
+ public void remove(String id, Class cls)
+ throws RollerException;
+
+ /**
+ * Release existing resources and start new session and transaction.
+ */
+ public void begin(UserData user) throws RollerException;
+
+ /**
+ * Associate user with thread.
+ */
+ public void setUser(UserData user) throws RollerException;
+ public UserData getUser() throws RollerException;
+
+ /**
+ * Commit all changes made to persistent objects since last call to begin.
+ */
+ public void commit() throws RollerException;
+
+ /**
+ * Rollback all changes since last call to begin.
+ */
+ public void rollback() throws RollerException;
+
+ /**
+ * Release associated resources (database connection, session, etc.) and
+ * clear thread local storage.
+ */
+ public void release() throws RollerException;
+}
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/PingQueueManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/PingQueueManagerImpl.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/PingQueueManagerImpl.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/PingQueueManagerImpl.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2005
+ * Anil R. Gangolli. All rights reserved.
+ *
+ * Distributed with the Roller Weblogger Project under the terms of the Roller Software
+ * License
+ */
+
+package org.roller.business;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.RollerException;
+import org.roller.model.PingQueueManager;
+import org.roller.pojos.PingQueueEntryData;
+
+/**
+ * Abstract implementation of PingQueueManager.
+ */
+public abstract class PingQueueManagerImpl implements PingQueueManager
+{
+ protected PersistenceStrategy persistenceStrategy;
+
+ private static Log logger = LogFactory.getLog(PingQueueManagerImpl.class);
+
+ public PingQueueManagerImpl(PersistenceStrategy persistenceStrategy)
+ {
+ this.persistenceStrategy = persistenceStrategy;
+ }
+
+ public void release()
+ {
+ }
+
+ public PingQueueEntryData retrieveQueueEntry(String id) throws RollerException
+ {
+ return (PingQueueEntryData) persistenceStrategy.load(id, PingQueueEntryData.class);
+ }
+
+ public void storeQueueEntry(PingQueueEntryData pingQueueEntry) throws RollerException
+ {
+ if (logger.isDebugEnabled()) logger.debug("Storing ping queue entry: " + pingQueueEntry);
+ persistenceStrategy.store(pingQueueEntry);
+ }
+
+ public void removeQueueEntry(String id) throws RollerException
+ {
+ if (logger.isDebugEnabled()) logger.debug("Removing ping queue entry with id: " + id);
+ persistenceStrategy.remove(id, PingQueueEntryData.class);
+ }
+
+ public void removeQueueEntry(PingQueueEntryData pingQueueEntry) throws RollerException
+ {
+ if (logger.isDebugEnabled()) logger.debug("Removing ping queue entry: " + pingQueueEntry);
+ persistenceStrategy.remove(pingQueueEntry);
+ }
+
+}
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/PingTargetManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/PingTargetManagerImpl.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/PingTargetManagerImpl.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/PingTargetManagerImpl.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2005
+ * Anil R. Gangolli. All rights reserved.
+ *
+ * Distributed with the Roller Weblogger Project under the terms of the Roller Software
+ * License
+ */
+
+package org.roller.business;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.RollerException;
+import org.roller.model.AutoPingManager;
+import org.roller.model.PingTargetManager;
+import org.roller.model.RollerFactory;
+import org.roller.pojos.PingTargetData;
+import org.roller.pojos.WebsiteData;
+
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Abstract implementation of PingTargetManager.
+ */
+public abstract class PingTargetManagerImpl implements PingTargetManager
+{
+ protected PersistenceStrategy persistenceStrategy;
+
+ private static Log mLogger =
+ LogFactory.getFactory().getInstance(PingTargetManagerImpl.class);
+
+ public PingTargetManagerImpl(PersistenceStrategy persistenceStrategy)
+ {
+ this.persistenceStrategy = persistenceStrategy;
+ }
+
+ public void release()
+ {
+ }
+
+ public PingTargetData createCommonPingTarget(String name, String pingUrl) throws RollerException
+ {
+ return new PingTargetData(null, name, pingUrl, null);
+ }
+
+ public PingTargetData createCustomPingTarget(String name, String pingUrl, WebsiteData website) throws RollerException
+ {
+ if (website == null) throw new RollerException(new IllegalArgumentException("website == null"));
+ return new PingTargetData(null, name, pingUrl, website);
+ }
+
+ public void storePingTarget(PingTargetData pingTarget) throws RollerException
+ {
+ persistenceStrategy.store(pingTarget);
+ }
+
+ public PingTargetData retrievePingTarget(String id) throws RollerException
+ {
+ return (PingTargetData) persistenceStrategy.load(id, PingTargetData.class);
+ }
+
+ public void removePingTarget(String id) throws RollerException
+ {
+ // The retrieval is necessary in order to do the necessary cleanup of references in pingTarget.remove().
+ PingTargetData pingTarget = retrievePingTarget(id);
+ pingTarget.remove();
+ }
+
+ public boolean isNameUnique(PingTargetData pingTarget) throws RollerException
+ {
+ String name = pingTarget.getName();
+ if (name == null || name.trim().length() == 0) return false;
+
+ String id = pingTarget.getId();
+
+ // Determine the set of "brother" targets (custom or common) among which this name should be unique.
+ List brotherTargets = null;
+ WebsiteData website = pingTarget.getWebsite();
+ if (website == null)
+ {
+ brotherTargets = getCommonPingTargets();
+ }
+ else
+ {
+ brotherTargets = getCustomPingTargets(website);
+ }
+
+ // Within that set of targets, fail if there is a target with the same name and that target doesn't
+ // have the same id.
+ for (Iterator i = brotherTargets.iterator(); i.hasNext();)
+ {
+ PingTargetData brother = (PingTargetData) i.next();
+ // Fail if it has the same name but not the same id.
+ if (brother.getName().equals(name) && (id == null || !brother.getId().equals(id)))
+ {
+ return false;
+ }
+ }
+ // No conflict found
+ return true;
+ }
+
+ public boolean isUrlWellFormed(PingTargetData pingTarget) throws RollerException
+ {
+ String url = pingTarget.getPingUrl();
+ if (url == null || url.trim().length() == 0) return false;
+ try
+ {
+ URL parsedUrl = new URL(url);
+ // OK. If we get here, it parses ok. Now just check that the protocol is http and there is a host portion.
+ boolean isHttp = parsedUrl.getProtocol().equals("http");
+ boolean hasHost = (parsedUrl.getHost() != null) && (parsedUrl.getHost().trim().length() > 0);
+ return isHttp && hasHost;
+ }
+ catch (MalformedURLException e)
+ {
+ return false;
+ }
+ }
+
+ public boolean isHostnameKnown(PingTargetData pingTarget) throws RollerException
+ {
+ String url = pingTarget.getPingUrl();
+ if (url == null || url.trim().length() == 0) return false;
+ try
+ {
+ URL parsedUrl = new URL(url);
+ String host = parsedUrl.getHost();
+ if (host == null || host.trim().length() == 0) return false;
+ InetAddress addr = InetAddress.getByName(host);
+ return true;
+ }
+ catch (MalformedURLException e)
+ {
+ return false;
+ }
+ catch (UnknownHostException e)
+ {
+ return false;
+ }
+ }
+}
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/PlanetManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/PlanetManagerImpl.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/PlanetManagerImpl.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/PlanetManagerImpl.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,230 @@
+package org.roller.business;
+
+import java.net.URL;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.text.MessageFormat;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.RollerException;
+import org.roller.model.PlanetManager;
+import org.roller.model.Roller;
+import org.roller.pojos.PlanetConfigData;
+import org.roller.pojos.PlanetEntryData;
+import org.roller.pojos.PlanetGroupData;
+import org.roller.pojos.PlanetSubscriptionData;
+import org.roller.util.rome.DiskFeedInfoCache;
+import org.roller.util.LRUCache2;
+
+import com.sun.syndication.feed.synd.SyndEntry;
+import com.sun.syndication.feed.synd.SyndFeed;
+import com.sun.syndication.fetcher.FeedFetcher;
+import com.sun.syndication.fetcher.impl.FeedFetcherCache;
+import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher;
+import com.sun.syndication.fetcher.impl.SyndFeedInfo;
+
+/**
+ * Base class for PlanetManager implementations.
+ * @author Dave Johnson
+ */
+public abstract class PlanetManagerImpl implements PlanetManager
+{
+ protected Roller roller = null;
+ protected PersistenceStrategy strategy;
+
+ // Cache up to 20 aggregations, each for up to 30 minutes
+ // TODO: make this aggregation cache configurable
+ protected LRUCache2 aggregationsByGroup =
+ new LRUCache2(20, 30 * 60 * 1000);
+
+ // Cache up to 20 aggregations, each for up to 30 minutes
+ // TODO: make this top-subscriptions cache configurable
+ protected LRUCache2 topSubscriptionsByGroup =
+ new LRUCache2(20, 30 * 60 * 1000);
+
+ private static Log logger =
+ LogFactory.getFactory().getInstance(PlanetManagerImpl.class);
+
+ public PlanetManagerImpl()
+ {
+ }
+
+ public PlanetManagerImpl(PersistenceStrategy strategy, Roller roller)
+ {
+ this.strategy = strategy;
+ this.roller = roller;
+ }
+
+ public void refreshEntries() throws RollerException
+ {
+ Date now = new Date();
+ long startTime = System.currentTimeMillis();
+ PlanetConfigData config = getConfiguration();
+ if (config == null || config.getCacheDir() == null)
+ {
+ logger.warn("Planet cache directory not set, aborting refresh");
+ return;
+ }
+ FeedFetcherCache feedInfoCache =
+ new DiskFeedInfoCache(config.getCacheDir());
+
+ if (config.getProxyHost()!=null && config.getProxyPort() > 0)
+ {
+ System.setProperty("proxySet", "true");
+ System.setProperty("http.proxyHost", config.getProxyHost());
+ System.setProperty("http.proxyPort",
+ Integer.toString(config.getProxyPort()));
+ }
+ /** a hack to set 15 sec timeouts for java.net.HttpURLConnection */
+ System.setProperty("sun.net.client.defaultConnectTimeout", "15000");
+ System.setProperty("sun.net.client.defaultReadTimeout", "15000");
+
+ FeedFetcher feedFetcher = new HttpURLFeedFetcher(feedInfoCache);
+ //FeedFetcher feedFetcher = new HttpClientFeedFetcher(feedInfoCache);
+ feedFetcher.setUsingDeltaEncoding(false);
+ feedFetcher.setUserAgent("Roller Planet 1.1-dev");
+
+ // Loop through all subscriptions in the system
+ Iterator subs = getAllSubscriptions();
+ while (subs.hasNext())
+ {
+ long subStartTime = System.currentTimeMillis();
+
+ // Fetch latest entries for each subscription
+ Set newEntries = new TreeSet();
+ PlanetSubscriptionData sub = (PlanetSubscriptionData)subs.next();
+ SyndFeed feed = null;
+ URL feedUrl = null;
+ Date lastUpdated = now;
+ try
+ {
+ feedUrl = new URL(sub.getFeedUrl());
+ logger.debug("Get feed from cache "+sub.getFeedUrl());
+ feed = feedFetcher.retrieveFeed(feedUrl);
+ SyndFeedInfo feedInfo = feedInfoCache.getFeedInfo(feedUrl);
+ if (feedInfo.getLastModified() != null)
+ {
+ long lastUpdatedLong =
+ ((Long)feedInfo.getLastModified()).longValue();
+ if (lastUpdatedLong != 0)
+ {
+ lastUpdated = new Date(lastUpdatedLong);
+ }
+ }
+ Thread.sleep(100); // be nice
+ }
+ catch (Exception e)
+ {
+ logger.warn("ERROR parsing " + sub.getFeedUrl()
+ + " : " + e.getClass().getName() + " : " + e.getMessage());
+ logger.debug(e);
+ continue;
+ }
+ if (lastUpdated!=null && sub.getLastUpdated()!=null)
+ {
+ Calendar feedCal = Calendar.getInstance();
+ feedCal.setTime(lastUpdated);
+
+ Calendar subCal = Calendar.getInstance();
+ subCal.setTime(sub.getLastUpdated());
+
+ if (!feedCal.after(subCal))
+ {
+ if (logger.isDebugEnabled())
+ {
+ String msg = MessageFormat.format(
+ " Skipping ({0} / {1})",
+ new Object[] {
+ lastUpdated, sub.getLastUpdated()});
+ logger.debug(msg);
+ }
+ continue;
+ }
+ }
+ if (feed.getPublishedDate() != null)
+ {
+ sub.setLastUpdated(feed.getPublishedDate());
+ saveSubscription(sub);
+ }
+
+ // Kludge for Feeds without entry dates: most recent entry is given
+ // feed's last publish date (or yesterday if none exists) and earler
+ // entries are placed at once day intervals before that.
+ Calendar cal = Calendar.getInstance();
+ if (sub.getLastUpdated() != null)
+ {
+ cal.setTime(sub.getLastUpdated());
+ }
+ else
+ {
+ cal.setTime(new Date());
+ cal.add(Calendar.DATE, -1);
+ }
+
+ // Populate subscription object with new entries
+ int count = 0;
+ Iterator entries = feed.getEntries().iterator();
+ while (entries.hasNext())
+ {
+ try
+ {
+ SyndEntry romeEntry = (SyndEntry) entries.next();
+ PlanetEntryData entry =
+ new PlanetEntryData(feed, romeEntry, sub);
+ if (entry.getPublished() == null)
+ {
+ logger.debug(
+ "No published date, assigning fake date for "+feedUrl);
+ entry.setPublished(cal.getTime());
+ }
+ if (entry.getPermalink() == null)
+ {
+ logger.warn("No permalink, rejecting entry from "+feedUrl);
+ }
+ else
+ {
+ saveEntry(entry);
+ newEntries.add(entry);
+ }
+ cal.add(Calendar.DATE, -1);
+ count++;
+ }
+ catch (Exception e)
+ {
+ logger.error("ERROR processing subscription entry", e);
+ }
+ }
+ logger.debug(" Entry count: " + count);
+ if (count > 0)
+ {
+ Iterator entryIter = sub.getEntries().iterator();
+ while (entryIter.hasNext())
+ {
+ deleteEntry((PlanetEntryData)entryIter.next());
+ }
+ sub.purgeEntries();
+ sub.addEntries(newEntries);
+ if (roller != null) roller.commit();
+ }
+ long subEndTime = System.currentTimeMillis();
+ logger.info(" " + count + " - "
+ + ((subEndTime-subStartTime)/1000.0)
+ + " seconds to process (" + count + ") entries of "
+ + sub.getFeedUrl());
+ }
+ // Clear the aggregation cache
+ clearCachedAggregations();
+
+ long endTime = System.currentTimeMillis();
+ logger.info("--- DONE --- Refreshed entries in "
+ + ((endTime-startTime)/1000.0) + " seconds");
+ }
+
+}
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/PropertiesManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/PropertiesManagerImpl.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/PropertiesManagerImpl.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/PropertiesManagerImpl.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,247 @@
+/*
+ * PropertiesManagerImpl.java
+ *
+ * Created on April 21, 2005, 10:43 AM
+ */
+
+package org.roller.business;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.RollerException;
+import org.roller.model.PropertiesManager;
+import org.roller.model.Roller;
+import org.roller.model.RollerFactory;
+import org.roller.pojos.RollerConfigData;
+import org.roller.pojos.RollerPropertyData;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
+import org.roller.config.RollerRuntimeConfig;
+import org.roller.config.runtime.ConfigDef;
+import org.roller.config.runtime.DisplayGroup;
+import org.roller.config.runtime.PropertyDef;
+import org.roller.config.runtime.RuntimeConfigDefs;
+
+/**
+ * Abstract PropertiesManager implementation.
+ *
+ * @author Allen Gilliland
+ */
+public abstract class PropertiesManagerImpl implements PropertiesManager
+{
+
+ protected PersistenceStrategy mStrategy;
+
+ private static Log mLogger =
+ LogFactory.getFactory().getInstance(PropertiesManagerImpl.class);
+
+
+ /**
+ * Creates a new instance of PropertiesManagerImpl
+ */
+ public PropertiesManagerImpl(PersistenceStrategy strategy)
+ {
+ this.mStrategy = strategy;
+ init();
+ }
+
+ private void init()
+ {
+ Map props = null;
+ try
+ {
+ props = this.getProperties();
+
+ if(props.size() < 1) {
+ // empty props table ... try migrating, then load defaults
+ props = migrateOldRollerConfig(props);
+ props = initializeMissingProps(props);
+ } else {
+ // found existing props ... check for new props
+ props = initializeMissingProps(props);
+ }
+
+ // save our changes
+ this.store(props);
+ }
+ catch (Exception e)
+ {
+ mLogger.fatal("Failed to initialize runtime configuration properties."+
+ "Please check that the database has been upgraded!", e);
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ /**
+ * Save a single property
+ */
+ public void store(RollerPropertyData property) throws RollerException
+ {
+ this.mStrategy.store(property);
+ }
+
+ /**
+ * Save all properties
+ */
+ public void store(Map properties) throws RollerException
+ {
+ // just go through the list and store each property
+ Iterator props = properties.values().iterator();
+ while (props.hasNext())
+ {
+ try
+ {
+ this.mStrategy.store((RollerPropertyData) props.next());
+ }
+ catch (RollerException re)
+ {
+ mLogger.error("Couldn't store Roller property", re);
+ throw re;
+ }
+ }
+ }
+
+ public void release()
+ {
+ }
+
+
+ /**
+ * Migrate data from the old roller config.
+ * This is called only if the existing runtime properties are empty.
+ */
+ private Map migrateOldRollerConfig(Map props)
+ {
+ // try to get the old config
+ Roller roller = RollerFactory.getRoller();
+ RollerConfigData rollerConfig = null;
+
+ try
+ {
+ rollerConfig = roller.getConfigManager().getRollerConfig();
+ }
+ catch (Exception e)
+ {
+ // We currently treat any exception obtaining the roller config
+ // as if we had not found it.
+ mLogger.error(e);
+ }
+
+ if (rollerConfig != null)
+ {
+ mLogger.info("Found old roller config ... doing migration to new runtime properties.");
+ // copy over data
+ props.put("site.name",
+ new RollerPropertyData("site.name", rollerConfig.getSiteName()));
+ props.put("site.description",
+ new RollerPropertyData("site.description", rollerConfig.getSiteDescription()));
+ props.put("site.adminemail",
+ new RollerPropertyData("site.adminemail", rollerConfig.getEmailAddress()));
+ props.put("site.absoluteurl",
+ new RollerPropertyData("site.absoluteurl", rollerConfig.getAbsoluteURL()));
+ props.put("site.linkbacks.enabled",
+ new RollerPropertyData("site.linkbacks.enabled", rollerConfig.getEnableLinkback().toString()));
+ props.put("users.registration.enabled",
+ new RollerPropertyData("users.registration.enabled", rollerConfig.getNewUserAllowed().toString()));
+ props.put("users.themes.path",
+ new RollerPropertyData("users.themes.path", rollerConfig.getUserThemes()));
+ props.put("users.editor.pages",
+ new RollerPropertyData("users.editor.pages", rollerConfig.getEditorPages()));
+ props.put("users.comments.enabled",
+ new RollerPropertyData("users.comments.enabled", "true"));
+ props.put("users.comments.autoformat",
+ new RollerPropertyData("users.comments.autoformat", rollerConfig.getAutoformatComments().toString()));
+ props.put("users.comments.escapehtml",
+ new RollerPropertyData("users.comments.escapehtml", rollerConfig.getEscapeCommentHtml().toString()));
+ props.put("users.comments.emailnotify",
+ new RollerPropertyData("users.comments.emailnotify", rollerConfig.getEmailComments().toString()));
+ props.put("uploads.enabled",
+ new RollerPropertyData("uploads.enabled", rollerConfig.getUploadEnabled().toString()));
+ props.put("uploads.types.allowed",
+ new RollerPropertyData("uploads.types.allowed", rollerConfig.getUploadAllow()));
+ props.put("uploads.types.forbid",
+ new RollerPropertyData("uploads.types.forbid", rollerConfig.getUploadForbid()));
+ props.put("uploads.file.maxsize",
+ new RollerPropertyData("uploads.file.maxsize", rollerConfig.getUploadMaxFileMB().toString()));
+ props.put("uploads.dir.maxsize",
+ new RollerPropertyData("uploads.dir.maxsize", rollerConfig.getUploadMaxDirMB().toString()));
+ /* no longer part of runtime config
+ props.put("aggregator.enabled",
+ new RollerPropertyData("aggregator.enabled", rollerConfig.getEnableAggregator().toString()));
+ props.put("aggregator.cache.enabled",
+ new RollerPropertyData("aggregator.cache.enabled", rollerConfig.getRssUseCache().toString()));
+ props.put("aggregator.cache.timeout",
+ new RollerPropertyData("aggregator.cache.timeout", rollerConfig.getRssCacheTime().toString()));
+ props.put("debug.memory.enabled",
+ new RollerPropertyData("debug.memory.enabled", rollerConfig.getMemDebug().toString()));
+ */
+ props.put("spam.referers.ignorewords",
+ new RollerPropertyData("spam.referers.ignorewords", rollerConfig.getRefererSpamWords()));
+ }
+ else
+ {
+ mLogger.info("Old roller config not found ... default values will be loaded");
+ }
+
+ return props;
+ }
+
+
+ /**
+ * This method compares the property definitions in the RuntimeConfigDefs
+ * file with the properties in the given Map and initializes any properties
+ * that were not found in the Map.
+ *
+ * If the Map of props is empty/null then we will initialize all properties.
+ **/
+ private Map initializeMissingProps(Map props) {
+
+ if(props == null)
+ props = new HashMap();
+
+ // start by getting our runtimeConfigDefs
+ RuntimeConfigDefs runtimeConfigDefs =
+ RollerRuntimeConfig.getRuntimeConfigDefs();
+
+ // can't do initialization without our config defs
+ if(runtimeConfigDefs == null)
+ return props;
+
+ // iterator through all the definitions and add properties
+ // that are not already in our props map
+ ConfigDef configDef = null;
+ DisplayGroup dGroup = null;
+ PropertyDef propDef = null;
+ Iterator defs = runtimeConfigDefs.getConfigDefs().iterator();
+ while(defs.hasNext()) {
+ configDef = (ConfigDef) defs.next();
+
+ Iterator groups = configDef.getDisplayGroups().iterator();
+ while(groups.hasNext()) {
+ dGroup = (DisplayGroup) groups.next();
+
+ Iterator propdefs = dGroup.getPropertyDefs().iterator();
+ while(propdefs.hasNext()) {
+ propDef = (PropertyDef) propdefs.next();
+
+ // do we already have this prop? if not then add it
+ if(!props.containsKey(propDef.getName())) {
+ RollerPropertyData newprop =
+ new RollerPropertyData(propDef.getName(), propDef.getDefaultValue());
+
+ props.put(propDef.getName(), newprop);
+
+ mLogger.info("Found uninitialized property "+propDef.getName()+
+ " ... setting value to ["+propDef.getDefaultValue()+"]");
+ }
+ }
+ }
+ }
+
+ return props;
+ }
+
+}
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/PubTimeData.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/PubTimeData.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/PubTimeData.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/PubTimeData.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,122 @@
+package org.roller.business;
+
+/**
+ * Pub date bean.
+ * @author David M Johnson
+ *
+ * @castor:class name="PubTime" table="weblogentry" id="id" key-generator="UUID"
+ */
+public class PubTimeData
+ extends org.roller.pojos.PersistentObject
+ implements java.io.Serializable
+{
+ static final long serialVersionUID = -5669288520200229343L;
+
+ protected java.lang.String id;
+ protected java.sql.Timestamp pubTime;
+
+ public PubTimeData()
+ {
+ }
+
+ public PubTimeData( java.lang.String id,java.sql.Timestamp pubTime )
+ {
+ this.id = id;
+ this.pubTime = pubTime;
+ }
+
+ public PubTimeData( PubTimeData otherData )
+ {
+ this.id = otherData.id;
+ this.pubTime = otherData.pubTime;
+
+ }
+
+ /** @castor:field set-method="setId"
+ * @castor:field-sql name="id" sql-dirty="check" dirty="check"
+ * @castor:field-xml node="attribute"
+ */
+ public java.lang.String getId()
+ {
+ return this.id;
+ }
+ public void setId( java.lang.String id )
+ {
+ this.id = id;
+ }
+
+ /** Pub date.
+ * @castor:field set-method="setPubTime"
+ * @castor:field-sql name="pubtime" sql-dirty="check" dirty="check"
+ */
+ public java.sql.Timestamp getPubTime()
+ {
+ return this.pubTime;
+ }
+ public void setPubTime( java.sql.Timestamp pubTime )
+ {
+ this.pubTime = pubTime;
+ }
+
+ public String toString()
+ {
+ StringBuffer str = new StringBuffer("{");
+
+ str.append("id=" + id + " " + "pubTime=" + pubTime);
+ str.append('}');
+
+ return(str.toString());
+ }
+
+ public boolean equals( Object pOther )
+ {
+ if( pOther instanceof PubTimeData )
+ {
+ PubTimeData lTest = (PubTimeData) pOther;
+ boolean lEquals = true;
+
+ if( this.id == null )
+ {
+ lEquals = lEquals && ( lTest.id == null );
+ }
+ else
+ {
+ lEquals = lEquals && this.id.equals( lTest.id );
+ }
+ if( this.pubTime == null )
+ {
+ lEquals = lEquals && ( lTest.pubTime == null );
+ }
+ else
+ {
+ lEquals = lEquals && this.pubTime.equals( lTest.pubTime );
+ }
+
+ return lEquals;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public int hashCode()
+ {
+ int result = 17;
+ result = 37*result + ((this.id != null) ? this.id.hashCode() : 0);
+ result = 37*result + ((this.pubTime != null) ? this.pubTime.hashCode() : 0);
+ return result;
+ }
+
+ /**
+ * Setter is needed in RollerImpl.storePersistentObject()
+ */
+ public void setData( org.roller.pojos.PersistentObject otherData )
+ {
+
+ this.id = ((PubTimeData)otherData).id;
+
+ this.pubTime = ((PubTimeData)otherData).pubTime;
+ }
+
+}
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/RefererManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/RefererManagerImpl.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/RefererManagerImpl.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/RefererManagerImpl.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,552 @@
+package org.roller.business;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.RollerException;
+import org.roller.config.RollerRuntimeConfig;
+import org.roller.model.ParsedRequest;
+import org.roller.model.RefererManager;
+import org.roller.model.Roller;
+import org.roller.model.RollerFactory;
+import org.roller.pojos.RefererData;
+import org.roller.pojos.WeblogEntryData;
+import org.roller.pojos.WebsiteData;
+import org.roller.util.DateUtil;
+import org.roller.util.LinkbackExtractor;
+import org.roller.util.Utilities;
+
+
+/**
+ * Abstract base implementation using PersistenceStrategy.
+ * @author Dave Johnson
+ * @author Lance Lavandowska
+ */
+public abstract class RefererManagerImpl implements RefererManager
+{
+ static Log mLogger =
+ LogFactory.getFactory().getInstance(RefererManagerImpl.class);
+
+ protected static final String DAYHITS = "dayHits";
+ protected static final String TOTALHITS = "totalHits";
+
+ protected PersistenceStrategy mStrategy;
+ protected Date mRefDate = new Date();
+ protected SimpleDateFormat mDateFormat = DateUtil.get8charDateFormat();
+
+ protected abstract List getReferersWithSameTitle(
+ WebsiteData website,
+ String requestUrl,
+ String title,
+ String excerpt)
+ throws RollerException;
+
+ protected abstract List getExistingReferers(
+ WebsiteData website,
+ String dateString,
+ String permalink) throws RollerException;
+
+ protected abstract List getReferersToWebsite(
+ WebsiteData website,
+ String refererUrl) throws RollerException;
+
+ protected abstract List getMatchingReferers(
+ WebsiteData website,
+ String requestUrl,
+ String refererUrl) throws RollerException;
+
+ //-----------------------------------------------------------------------
+
+ public RefererManagerImpl()
+ {
+ }
+
+ //-----------------------------------------------------------------------
+
+ protected abstract int getHits(WebsiteData website, String type)
+ throws RollerException;
+
+ //------------------------------------------------------------------------
+
+ public void release()
+ {
+ }
+
+ //-----------------------------------------------------------------------
+ public synchronized void forceTurnover(String websiteId) throws RollerException
+ {
+ mLogger.debug("forceTurnover");
+ checkForTurnover(true, websiteId);
+ }
+
+ //--------------------------------------------------------- Get hit counts
+
+ public int getDayHits(WebsiteData website) throws RollerException
+ {
+ return getHits(website, DAYHITS);
+ }
+
+ //-----------------------------------------------------------------------
+
+ public int getTotalHits(WebsiteData website) throws RollerException
+ {
+ return getHits(website, TOTALHITS);
+ }
+
+
+ //------------------------------------------------------- Referer Storage
+
+ /**
+ * @see org.roller.pojos.RefererManager#removeReferer(java.lang.String)
+ */
+ public void removeReferer(String id) throws RollerException
+ {
+ mStrategy.remove(id, RefererData.class);
+ }
+
+ //-----------------------------------------------------------------------
+
+ /**
+ * @see org.roller.pojos.RefererManager#retrieveReferer(java.lang.String)
+ */
+ public RefererData retrieveReferer(String id) throws RollerException
+ {
+ return (RefererData)mStrategy.load(id,RefererData.class);
+ }
+
+ //-----------------------------------------------------------------------
+
+ /**
+ * @see org.roller.pojos.RefererManager#storeReferer(
+ * org.roller.pojos.RefererData)
+ */
+ public void storeReferer(RefererData data) throws RollerException
+ {
+ mStrategy.store(data);
+ }
+
+ //-----------------------------------------------------------------------
+ public List getEntryReferers(String entryId, boolean authorized)
+ throws RollerException
+ {
+ //TODO: Redesign this so this is performed using the DB query, and
+ // not in java code for perf/memory reasons
+ List authorizedvisible = new ArrayList();
+ List referers = getReferersToEntry(entryId);
+ for (Iterator rItr = referers.iterator(); rItr.hasNext();)
+ {
+ RefererData referer = (RefererData) rItr.next();
+ if ( referer.getVisible().booleanValue() || authorized )
+ {
+ authorizedvisible.add( referer );
+ }
+ }
+
+ return authorizedvisible;
+ }
+
+ //------------------------------------------------------------------------
+
+ /**
+ * Process incoming request for referer information.
+ *
+ * <p>If there is no referer, treat it as a direct request.</p>
+ *
+ * <p>If there is a referer and there is no record for that referer, then
+ * parse the refering page for title and excerpt surround the refering link.
+ * If the excerpt cannot be found, then ignore the referer because it is
+ * fake - probably a referer spam.
+ * </p>
+ *
+ * @return boolean True if the referer header contains an ignore/spam word.
+ * @see org.roller.pojos.RefererManager#processRequest(ParsedRequest)
+ */
+ public boolean processRequest( ParsedRequest request )
+ {
+ String msg = "processRequest";
+ if ( request.getWebsite() == null ) return false;
+
+ try
+ {
+ List matchRef = null;
+
+ String requestUrl = request.getRequestURL();
+ String refererUrl = request.getRefererURL();
+ WebsiteData website = request.getWebsite();
+ WeblogEntryData entry = request.getWeblogEntry();
+ String selfSiteFragment = "/page/" + website.getUser().getUserName();
+
+ String dateString = null;
+ if ( request.getDateString()!=null && request.isDateSpecified())
+ {
+ dateString = request.getDateString();
+ }
+
+ if (mLogger.isDebugEnabled())
+ {
+ mLogger.debug( msg+": refurl="+refererUrl );
+ }
+
+ /* Check Referer URL against selfSiteFragment (treat as direct),
+ * against a regex for an self-site editor page (direct),
+ * and against the Spam lists.
+ */
+ if ( refererUrl != null )
+ {
+ // treat own URL as direct
+ if (refererUrl.indexOf(selfSiteFragment) != -1)
+ {
+ refererUrl = null;
+ }
+ else
+ {
+ // treat editor referral as direct
+ int lastSlash = requestUrl.indexOf("/", 8);
+ if (lastSlash == -1) lastSlash = requestUrl.length();
+ String requestSite = requestUrl.substring(0, lastSlash);
+ if (refererUrl.matches(requestSite + ".*\\.do.*"))
+ {
+ refererUrl = null;
+ }
+ else
+ {
+ // If referer URL contains spamWords or ignoreWords then don't log it.
+ boolean isRefererSpam = checkForSpam(refererUrl, website);
+ if (isRefererSpam) return true;
+ }
+ }
+ }
+
+ // try to find existing RefererData for refererUrl
+ if (refererUrl == null || refererUrl.trim().length() < 8)
+ {
+ refererUrl = "direct";
+
+ // Get referer specified by referer URL of direct
+ matchRef = getReferersToWebsite(website, refererUrl);
+ }
+ else
+ {
+ refererUrl = Utilities.stripJsessionId(refererUrl);
+
+ // Query for referer with same referer and request URLs
+ matchRef = getMatchingReferers(website, requestUrl, refererUrl);
+
+ // If referer was not found, try adding or leaving off 'www'
+ if ( matchRef.size() == 0 )
+ {
+ String secondTryUrl = null;
+ if ( refererUrl.startsWith("http://www") )
+ {
+ secondTryUrl = "http://"+refererUrl.substring(11);
+ }
+ else
+ {
+ secondTryUrl = "http://www"+refererUrl.substring(7);
+ }
+
+ matchRef = getMatchingReferers(
+ website, requestUrl, secondTryUrl);
+ if ( matchRef.size() == 1 )
+ {
+ refererUrl = secondTryUrl;
+ }
+ }
+ }
+
+ if (matchRef.size() == 1)
+ {
+ // Referer was found in database, so bump up hit count
+ RefererData ref = (RefererData)matchRef.get(0);
+
+ ref.setDayHits(
+ new Integer(ref.getDayHits().intValue() + 1));
+ ref.setTotalHits(
+ new Integer(ref.getTotalHits().intValue() + 1));
+
+ if (mLogger.isDebugEnabled())
+ {
+ mLogger.debug(
+ "Incrementing hit count on existing referer: "+refererUrl);
+ }
+
+ storeReferer(ref);
+ mStrategy.commit();
+ }
+ else if (matchRef.size() == 0)
+ {
+ // Referer was not found in database, so new Referer object
+ Integer one = new Integer(1);
+ RefererData ref =
+ new RefererData(
+ null,
+ website,
+ entry,
+ dateString,
+ refererUrl,
+ null,
+ requestUrl,
+ null,
+ null,
+ Boolean.FALSE,
+ Boolean.FALSE,
+ one,
+ one);
+
+ if (mLogger.isDebugEnabled())
+ {
+ mLogger.debug("newReferer="+ref.getRefererUrl());
+ }
+
+ String refurl = ref.getRefererUrl();
+
+ // If not a direct or search engine then search for linkback
+ if ( request.isEnableLinkback()
+ && request.isDateSpecified()
+ && !refurl.equals("direct")
+ && !refurl.startsWith("http://google")
+ && !refurl.startsWith("http://www.google")
+ && !refurl.startsWith("http://search.netscape")
+ && !refurl.startsWith("http://www.blinkpro")
+ && !refurl.startsWith("http://auto.search.msn")
+ && !refurl.startsWith("http://search.yahoo")
+ && !refurl.startsWith("http://uk.search.yahoo")
+ && !refurl.startsWith("http://www.javablogs.com")
+ && !refurl.startsWith("http://www.teoma")
+ )
+ {
+ // Launch thread to extract referer linkback
+
+ try
+ {
+ Roller mRoller = RollerFactory.getRoller();
+ mRoller.getThreadManager().executeInBackground(
+ new LinkbackExtractorRunnable(ref) );
+ }
+ catch (InterruptedException e) {
+ mLogger.warn("Interrupted during linkback extraction",e);
+ }
+ }
+ else
+ {
+ storeReferer(ref);
+ mStrategy.commit();
+ }
+ }
+ }
+ catch (RollerException pe)
+ {
+ mLogger.error(msg, pe);
+ }
+ catch (NullPointerException npe)
+ {
+ mLogger.error(msg, npe);
+ }
+
+ return false;
+ }
+
+ /**
+ * Check the Referer URL against the Site-wide RefererSpamWords list
+ * and against the user's own IgnoreWords list. If the Referer contains
+ * any of the words from either list consider it Spam.
+ *
+ * @param refererUrl
+ * @return
+ * @throws RollerException
+ */
+ private boolean checkForSpam(String refererUrl, WebsiteData website) throws RollerException
+ {
+ String spamwords = RollerRuntimeConfig.getProperty("spam.referers.ignorewords");
+ LinkedList spamWords = new LinkedList(Arrays.asList(
+ StringUtils.split(StringUtils.deleteWhitespace(spamwords), ",")));
+
+ if ( website.getIgnoreWords() != null )
+ {
+ spamWords.addAll(
+ Arrays.asList(StringUtils.split(
+ StringUtils.deleteWhitespace(
+ website.getIgnoreWords()),",")));
+ }
+ for( Iterator i = spamWords.iterator(); i.hasNext(); )
+ {
+ String word = (String)i.next();
+ if (refererUrl.indexOf(word) != -1)
+ {
+ if (mLogger.isDebugEnabled())
+ {
+ mLogger.debug("Flagged a Spam because '" + word +
+ "' was found in '" + refererUrl + "'");
+ }
+ refererUrl = null;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Use LinkbackExtractor to parse title and excerpt from referer
+ */
+ class LinkbackExtractorRunnable implements Runnable
+ {
+
+ private RefererData mReferer = null;
+
+ public LinkbackExtractorRunnable( RefererData referer)
+ {
+ mReferer = referer;
+ }
+
+ public void run()
+ {
+
+ try
+ {
+ LinkbackExtractor lb = new LinkbackExtractor(
+ mReferer.getRefererUrl(),mReferer.getRequestUrl());
+
+ if ( lb.getTitle()!=null && lb.getExcerpt()!=null )
+ {
+ mReferer.setTitle(lb.getTitle());
+ mReferer.setExcerpt(lb.getExcerpt());
+
+
+ if ( lb.getPermalink() != null )
+ {
+ // The presence of a permalink indicates that this
+ // linkback was parsed out of an RSS feed and is
+ // presumed to be a good linkback.
+
+ mReferer.setRefererPermalink(lb.getPermalink());
+
+ // See if this request/permalink is in the DB
+ List matchRef = getExistingReferers(
+ mReferer.getWebsite(),
+ mReferer.getDateString(),
+ mReferer.getRefererPermalink());
+
+ // If it is the first, then set it to be visible
+ if ( matchRef.size() == 0 )
+ {
+ mReferer.setVisible(Boolean.TRUE);
+ }
+ else
+ {
+ // We can't throw away duplicates or we will
+ // end up reparsing them everytime a hit comes
+ // in from one of them, but we can mark them
+ // as duplicates.
+ mReferer.setDuplicate(Boolean.TRUE);
+ }
+
+ storeReferer(mReferer);
+ }
+
+ else
+ {
+ // Store the new referer
+ storeReferer(mReferer);
+
+ // Hacky Referer URL weighting kludge:
+ //
+ // If there are multple referers to a request URL,
+ // then we want to pick the best one. The others
+ // are marked as duplicates. To do this we use a
+ // weight. The weight formula is:
+ //
+ // w = URL length + (100 if URL contains anchor)
+
+ // LOOP: find the referer with the highest weight
+ Boolean visible = Boolean.FALSE;
+ List refs= getReferersWithSameTitle(
+ mReferer.getWebsite(),
+ mReferer.getRequestUrl(),
+ lb.getTitle(),
+ lb.getExcerpt());
+ RefererData chosen = null;
+ int maxweight = 0;
+ for (Iterator rdItr = refs.iterator();rdItr.hasNext();)
+ {
+ RefererData referer = (RefererData) rdItr.next();
+
+ int weight = referer.getRefererUrl().length();
+ if (referer.getRefererUrl().indexOf('#') != -1)
+ {
+ weight += 100;
+ }
+
+ if ( weight > maxweight )
+ {
+ chosen = referer;
+ maxweight = weight;
+ }
+
+ if (referer.getVisible().booleanValue())
+ {
+ // If any are visible then chosen
+ // replacement must be visible as well.
+ visible = Boolean.TRUE;
+ }
+
+ }
+
+ // LOOP: to mark all of the lower weight ones
+ // as duplicates
+ for (Iterator rdItr = refs.iterator();rdItr.hasNext();) {
+ RefererData referer = (RefererData) rdItr.next();
+
+ if (referer != chosen)
+ {
+ referer.setDuplicate(Boolean.TRUE);
+ }
+ else
+ {
+ referer.setDuplicate(Boolean.FALSE);
+ referer.setVisible(visible);
+ }
+ storeReferer(referer);
+ }
+
+
+ }
+ }
+ else
+ {
+ // It is not a linkback, but store it anyway
+ storeReferer(mReferer);
+
+ mLogger.info("No excerpt found at refering URL "
+ + mReferer.getRefererUrl());
+ }
+ }
+ catch (Exception e)
+ {
+ mLogger.error("Processing linkback",e);
+ }
+ finally
+ {
+ try {
+ mStrategy.release();
+ }
+ catch (RollerException e) {
+ mLogger.error(
+ "Exception logged by ManagerSupport.releaseDatabase()");
+ }
+ }
+
+ }
+
+ }
+
+}
+
+
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/RollerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/RollerImpl.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/RollerImpl.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/RollerImpl.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,112 @@
+/*
+ * RollerImpl.java
+ *
+ * Created on April 29, 2005, 5:33 PM
+ */
+
+package org.roller.business;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.RollerException;
+import org.roller.model.FileManager;
+import org.roller.model.IndexManager;
+import org.roller.model.Roller;
+import org.roller.model.ThemeManager;
+import org.roller.model.ThreadManager;
+
+
+
+/**
+ * The abstract version of the Roller implementation.
+ * Here we put code that pertains to *all* implementations of the Roller
+ * interface, regardless of their persistence strategy.
+ *
+ * @author Allen Gilliland
+ */
+public abstract class RollerImpl implements Roller {
+
+ private static Log mLogger =
+ LogFactory.getFactory().getInstance(RollerImpl.class);
+
+ protected FileManager mFileManager = null;
+ protected IndexManager mIndexManager = null;
+ protected ThreadManager mThreadManager = null;
+ protected ThemeManager mThemeManager = null;
+
+
+ /** Creates a new instance of RollerImpl */
+ public RollerImpl() {
+ // nothing to do here yet
+ }
+
+
+ /**
+ * @see org.roller.model.Roller#getFileManager()
+ */
+ public FileManager getFileManager() throws RollerException
+ {
+ if (mFileManager == null)
+ {
+ mFileManager = new FileManagerImpl();
+ }
+ return mFileManager;
+ }
+
+ /**
+ * @see org.roller.model.Roller#getThreadManager()
+ */
+ public ThreadManager getThreadManager() throws RollerException
+ {
+ if (mThreadManager == null)
+ {
+ mThreadManager = new ThreadManagerImpl();
+ }
+ return mThreadManager;
+ }
+
+ /**
+ * @see org.roller.model.Roller#getIndexManager()
+ */
+ public IndexManager getIndexManager() throws RollerException
+ {
+ if (mIndexManager == null)
+ {
+ mIndexManager = new IndexManagerImpl();
+ }
+ return mIndexManager;
+ }
+
+ /**
+ * @see org.roller.model.Roller#getThemeManager()
+ */
+ public ThemeManager getThemeManager() throws RollerException
+ {
+ if (mThemeManager == null)
+ {
+ mThemeManager = new ThemeManagerImpl();
+ }
+ return mThemeManager;
+ }
+
+
+ public void release()
+ {
+ if (mFileManager != null) mFileManager.release();
+ if (mThreadManager != null) mThreadManager.release();
+ }
+
+
+ public void shutdown()
+ {
+ try
+ {
+ if (mIndexManager != null) mIndexManager.shutdown();
+ if (mThreadManager != null) mThreadManager.shutdown();
+ }
+ catch(Exception e)
+ {
+ mLogger.warn(e);
+ }
+ }
+}
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/ThemeManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/ThemeManagerImpl.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/ThemeManagerImpl.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/ThemeManagerImpl.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,276 @@
+/*
+ * ThemeManagerImpl.java
+ *
+ * Created on June 27, 2005, 1:33 PM
+ */
+
+package org.roller.business;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.RollerException;
+import org.roller.ThemeNotFoundException;
+import org.roller.config.RollerConfig;
+import org.roller.model.ThemeManager;
+import org.roller.pojos.Theme;
+import org.roller.pojos.ThemeTemplate;
+
+
+/**
+ * Base implementation of a ThemeManager.
+ *
+ * This particular implementation reads theme data off the filesystem
+ * and assumes that those themes are not changable at runtime.
+ *
+ * @author Allen Gilliland
+ */
+public class ThemeManagerImpl implements ThemeManager {
+
+ private static Log mLogger =
+ LogFactory.getFactory().getInstance(ThemeManagerImpl.class);
+
+ private Map themes;
+
+
+ protected ThemeManagerImpl() {
+
+ // rather than be lazy we are going to load all themes from
+ // the disk preemptively during initialization and cache them
+ mLogger.debug("Initializing ThemeManagerImpl");
+
+ this.themes = this.loadAllThemesFromDisk();
+ mLogger.info("Loaded "+this.themes.size()+" themes from disk.");
+ }
+
+
+ /**
+ * @see org.roller.model.ThemeManager#getTheme(java.lang.String)
+ */
+ public Theme getTheme(String name)
+ throws ThemeNotFoundException, RollerException {
+
+ Theme theme = (Theme) this.themes.get(name);
+ if(theme == null)
+ throw new ThemeNotFoundException("Couldn't find theme ["+name+"]");
+
+ return theme;
+ }
+
+
+ /**
+ * @see org.roller.model.ThemeManager#getThemeById(java.lang.String)
+ */
+ public Theme getThemeById(String id)
+ throws ThemeNotFoundException, RollerException {
+
+ // In this implementation where themes come from the filesystem we
+ // know that the name and id for a theme are the same
+ return this.getTheme(id);
+ }
+
+
+ /**
+ * @see org.roller.model.ThemeManager#getThemesList()
+ */
+ public List getThemesList() {
+
+ List themes = new ArrayList(this.themes.keySet());
+
+ // sort 'em ... the natural sorting order for Strings is alphabetical
+ Collections.sort(themes);
+
+ return themes;
+ }
+
+
+ /**
+ * @see org.roller.model.ThemeManager#getEnabledThemesList()
+ */
+ public List getEnabledThemesList() {
+
+ Collection all_themes = this.themes.values();
+
+ // make a new list of only the enabled themes
+ List enabled_themes = new ArrayList();
+ Iterator it = all_themes.iterator();
+ Theme theme = null;
+ while(it.hasNext()) {
+ theme = (Theme) it.next();
+ if(theme.isEnabled())
+ enabled_themes.add(theme.getName());
+ }
+
+ // sort 'em ... the natural sorting order for Strings is alphabetical
+ Collections.sort(enabled_themes);
+
+ return enabled_themes;
+ }
+
+
+ /**
+ * @see org.roller.model.ThemeManager#getTemplate(String, String)
+ */
+ public ThemeTemplate getTemplate(String theme_name, String template_name)
+ throws ThemeNotFoundException, RollerException {
+
+ // basically we just try and lookup the theme first, then template
+ Theme theme = this.getTheme(theme_name);
+
+ return theme.getTemplate(template_name);
+ }
+
+
+ /**
+ * @see org.roller.model.ThemeManager#getTemplateById(java.lang.String)
+ */
+ public ThemeTemplate getTemplateById(String id)
+ throws ThemeNotFoundException, RollerException {
+
+ if(id == null)
+ throw new ThemeNotFoundException("Theme id was null");
+
+ // in our case we expect a template id to be <theme>:<template>
+ // so extract each piece and do the lookup
+ String[] split = id.split(":", 2);
+ if(split.length != 2)
+ throw new ThemeNotFoundException("Invalid theme id ["+id+"]");
+
+ return this.getTemplate(split[0], split[1]);
+ }
+
+
+ /**
+ * @see org.roller.model.ThemeManager#getTemplateByLink(java.lang.String)
+ */
+ public ThemeTemplate getTemplateByLink(String theme_name, String template_link)
+ throws ThemeNotFoundException, RollerException {
+
+ // basically we just try and lookup the theme first, then template
+ Theme theme = this.getTheme(theme_name);
+
+ return theme.getTemplateByLink(template_link);
+ }
+
+
+ /**
+ * This is a convenience method which loads all the theme data from
+ * themes stored on the filesystem in the roller webapp /themes/ directory.
+ */
+ private Map loadAllThemesFromDisk() {
+
+ Map themes = new HashMap();
+
+ // NOTE: we need to figure out how to get the roller context path
+ String themespath = RollerConfig.getProperty("context.realpath");
+ if(themespath.endsWith(File.separator))
+ themespath += "themes";
+ else
+ themespath += File.separator + "themes";
+
+ // first, get a list of the themes available
+ File themesdir = new File(themespath);
+ FilenameFilter filter = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ File file =
+ new File(dir.getAbsolutePath() + File.separator + name);
+ return file.isDirectory();
+ }
+ };
+ String[] themenames = themesdir.list(filter);
+
+ if(themenames == null)
+ themenames = new String[0];
+
+ // now go through each theme and read all it's templates
+ Theme theme = null;
+ for(int i=0; i < themenames.length; i++) {
+ theme = this.loadThemeFromDisk(themenames[i],
+ themespath + File.separator + themenames[i]);
+
+ themes.put(theme.getName(), theme);
+ }
+
+ return themes;
+ }
+
+
+ /**
+ * Another convenience method which knows how to load a single theme
+ * off the filesystem and return a Theme object
+ */
+ private Theme loadThemeFromDisk(String theme_name, String themepath) {
+
+ mLogger.debug("Loading theme "+theme_name+" from "+themepath);
+
+ Theme theme = new Theme();
+ theme.setName(theme_name);
+ theme.setAuthor("Roller");
+ theme.setLastEditor("Roller");
+ theme.setEnabled(true);
+
+ // start by getting a list of the .vm files for this theme
+ File themedir = new File(themepath);
+ FilenameFilter filter = new FilenameFilter()
+ {
+ public boolean accept(File dir, String name)
+ {
+ return name.endsWith(".vm");
+ }
+ };
+ String[] templates = themedir.list(filter);
+
+ // go through each .vm file and read in its contents to a ThemeTemplate
+ String template_name = null;
+ ThemeTemplate theme_template = null;
+ for (int i=0; i < templates.length; i++) {
+ // strip off the .vm part
+ template_name = templates[i].substring(0, templates[i].length() - 3);
+
+ try {
+ File template_file = new File(themepath + File.separator + templates[i]);
+
+ if(!template_file.exists() && !template_file.canRead()) {
+ mLogger.warn("Couldn't read theme template file ["+template_file.getPath()+"]");
+ continue;
+ }
+
+ FileReader reader = new FileReader(template_file);
+ char[] chars = new char[(int) template_file.length()];
+ reader.read(chars);
+
+ // construct ThemeTemplate representing this file
+ theme_template = new ThemeTemplate(
+ theme_name+":"+template_name,
+ template_name,
+ template_name,
+ new String(chars),
+ template_name,
+ new Date(template_file.lastModified()));
+
+ // add it to the theme
+ theme.setTemplate(template_name, theme_template);
+
+ } catch (Exception e) {
+ // warn?
+ }
+ }
+
+ // use the last mod date of the last template file
+ // as the last mod date of the theme
+ theme.setLastModified(theme_template.getLastModified());
+
+ return theme;
+ }
+
+}
Added: incubator/roller/branches/roller_1.x/src/org/roller/business/ThreadManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_1.x/src/org/roller/business/ThreadManagerImpl.java?rev=327589&view=auto
==============================================================================
--- incubator/roller/branches/roller_1.x/src/org/roller/business/ThreadManagerImpl.java (added)
+++ incubator/roller/branches/roller_1.x/src/org/roller/business/ThreadManagerImpl.java Fri Oct 21 14:27:36 2005
@@ -0,0 +1,92 @@
+package org.roller.business;
+
+import EDU.oswego.cs.dl.util.concurrent.BoundedBuffer;
+import EDU.oswego.cs.dl.util.concurrent.DirectExecutor;
+import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
+import EDU.oswego.cs.dl.util.concurrent.ThreadFactory;
+
+import java.util.Date;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.roller.model.ThreadManager;
+import org.roller.util.DateUtil;
+
+/**
+ * Manage Roller's background thread use. Currently, Roller starts background
+ * threads for two purposes: 1) the nightly purge of referer counts and 2)
+ * following linkbacks (only occurs if linkbacks are enabled).
+ *
+ * @author aim4min
+ */
+public class ThreadManagerImpl implements ThreadManager
+{
+ private PooledExecutor backgroundExecutor;
+ private DirectExecutor nodelayExecutor;
+ private Timer scheduler;
+
+ public ThreadManagerImpl()
+ {
+ backgroundExecutor = new PooledExecutor(new BoundedBuffer(10), 25);
+ backgroundExecutor.setMinimumPoolSize(4);
+ backgroundExecutor.setKeepAliveTime(1000 * 60 * 5);
+ backgroundExecutor.waitWhenBlocked();
+ backgroundExecutor.createThreads(9);
+
+ backgroundExecutor.setThreadFactory(new ThreadFactory() {
+ public Thread newThread(Runnable command)
+ {
+ Thread t = new Thread(command);
+ t.setDaemon(false);
+ t.setName("Background Execution Threads");
+ t.setPriority(Thread.NORM_PRIORITY);
+
+ return t;
+ }
+ });
+
+ nodelayExecutor = new DirectExecutor();
+ scheduler = new Timer(true);
+ }
+
+ public void executeInBackground(Runnable runnable)
+ throws InterruptedException
+ {
+ backgroundExecutor.execute(runnable);
+ }
+
+ public void executeInForeground(Runnable runnable)
+ throws InterruptedException
+ {
+ nodelayExecutor.execute(runnable);
+ }
+
+ public void scheduleDailyTimerTask(TimerTask task)
+ {
+ scheduler.scheduleAtFixedRate(task,
+ DateUtil.getEndOfDay(new Date()), DateUtil.millisInDay);
+ }
+
+ public void scheduleHourlyTimerTask(TimerTask task)
+ {
+ scheduler.scheduleAtFixedRate(task, new Date(), 60*60*1000);
+ }
+
+ public void scheduleFixedRateTimerTask(TimerTask task, long delayMins, long periodMins) {
+ if (periodMins < MIN_RATE_INTERVAL_MINS) {
+ throw new IllegalArgumentException("Period (" + periodMins +
+ ") shorter than minimum allowed (" + MIN_RATE_INTERVAL_MINS + ")");
+ }
+ scheduler.scheduleAtFixedRate(task, delayMins * 60 * 1000, periodMins * 60 * 1000);
+ }
+
+ public void shutdown()
+ {
+ backgroundExecutor.shutdownAfterProcessingCurrentlyQueuedTasks();
+ scheduler.cancel();
+ }
+
+ public void release()
+ {
+ }
+}
\ No newline at end of file