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/06/09 05:19:20 UTC
svn commit: r189695 [18/67] - in /incubator/roller/trunk: ./ 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/src/org/roller/presentation/velocity/
contrib/plugins/src/org/roller/presentation/velocity/plugins/
contrib/plugins/src/org/roller/presentation/velocity/plugins/acronyms/
contrib/plugins/src/org/roller/presentation/velocity/plugins/bookmarks/
contrib/plugins/src/org/roller/presentation/velocity/plugins/email/
contrib/plugins/src/org/roller/presentation/velocity/plugins/jspwiki/
contrib/plugins/src/org/roller/presentation/velocity/plugins/radeox/
contrib/plugins/src/org/roller/presentation/velocity/plugins/readmore/
contrib/plugins/src/org/roller/presentation/velocity/plugins/smileys/
contrib/plugins/src/org/roller/presentation/velocity/plugins/textile/
contrib/plugins/src/org/roller/presentation/velocity/plugins/topictag/
custom/ custom/src/ custom/web/ docs/ docs/images/ docs/installguide/
docs/installguide/old/ docs/userguide/ docs/userguide/images/
docs/userguide/old/ metadata/ metadata/database/
metadata/database/hibernate/ metadata/xdoclet/ nbproject/ personal/
personal/eclipse/ personal/testing/ sandbox/ sandbox/planetroller/
sandbox/planetroller/metadata/ sandbox/planetroller/metadata/database/
sandbox/planetroller/src/ sandbox/planetroller/src/org/
sandbox/planetroller/src/org/roller/
sandbox/planetroller/src/org/roller/tools/
sandbox/planetroller/src/org/roller/tools/planet/
sandbox/planetroller/templates/ sandbox/planetroller/test/
sandbox/planetroller/test/org/ sandbox/planetroller/test/org/roller/
sandbox/planetroller/test/org/roller/model/
sandbox/planetroller/test/org/roller/tools/
sandbox/planetroller/test/org/roller/tools/planet/
sandbox/planetroller/testdata/ sandbox/planetroller/testdata/cache/
sandbox/planetroller/testdata/output/ sandbox/standalone/
sandbox/standalone/jspwiki/ sandbox/standalone/jspwiki/default/
sandbox/standalone/jspwiki/default/images/ sandbox/standalone/lib/
sandbox/standalone/src/ sandbox/standalone/src/org/
sandbox/standalone/src/org/roller/ sandbox/standalone/src/org/roller/jspwiki/
sandbox/standalone/src/org/roller/tomcat/
sandbox/standalone/src/org/roller/util/ sandbox/standalone/tests/
sandbox/standalone/tests/org/ sandbox/standalone/tests/org/roller/
sandbox/standalone/tests/org/roller/util/ sandbox/standalone/tomcat/ src/
src/org/ src/org/roller/ src/org/roller/business/
src/org/roller/business/hibernate/ src/org/roller/business/search/
src/org/roller/business/search/operations/ src/org/roller/business/utils/
src/org/roller/config/ src/org/roller/config/runtime/ src/org/roller/model/
src/org/roller/pojos/ src/org/roller/presentation/
src/org/roller/presentation/atomapi/ src/org/roller/presentation/bookmarks/
src/org/roller/presentation/bookmarks/actions/
src/org/roller/presentation/bookmarks/formbeans/
src/org/roller/presentation/bookmarks/tags/
src/org/roller/presentation/filters/ src/org/roller/presentation/forms/
src/org/roller/presentation/newsfeeds/ src/org/roller/presentation/pagecache/
src/org/roller/presentation/pagecache/rollercache/
src/org/roller/presentation/pings/ src/org/roller/presentation/planet/
src/org/roller/presentation/tags/ src/org/roller/presentation/tags/calendar/
src/org/roller/presentation/tags/menu/ src/org/roller/presentation/util/
src/org/roller/presentation/velocity/ src/org/roller/presentation/weblog/
src/org/roller/presentation/weblog/actions/
src/org/roller/presentation/weblog/formbeans/
src/org/roller/presentation/weblog/tags/ src/org/roller/presentation/website/
src/org/roller/presentation/website/actions/
src/org/roller/presentation/website/formbeans/
src/org/roller/presentation/website/tags/
src/org/roller/presentation/xmlrpc/ src/org/roller/util/
src/org/roller/util/rome/ tests/ tests/org/ tests/org/roller/
tests/org/roller/ant/ tests/org/roller/business/
tests/org/roller/presentation/ tests/org/roller/presentation/atomapi/
tests/org/roller/presentation/bookmarks/
tests/org/roller/presentation/filters/
tests/org/roller/presentation/velocity/
tests/org/roller/presentation/velocity/plugins/
tests/org/roller/presentation/velocity/plugins/smileys/
tests/org/roller/presentation/velocity/plugins/textile/
tests/org/roller/presentation/weblog/ tests/org/roller/presentation/xmlrpc/
tests/org/roller/util/ tests/org/roller/util/rome/ tools/ tools/buildtime/
tools/buildtime/ant-1.6.2/ tools/buildtime/findbugs/
tools/buildtime/findbugs/lib/ tools/buildtime/findbugs/plugin/
tools/buildtime/mockrunner-0.3/ tools/buildtime/mockrunner-0.3/lib/
tools/buildtime/mockrunner-0.35/ tools/buildtime/mockrunner-0.35/lib/
tools/buildtime/tomcat-4.1.24/ tools/buildtime/xdoclet-1.2/
tools/buildtime/xdoclet-1.2/lib/ tools/hibernate-2.1/
tools/hibernate-2.1/lib/ tools/lib/ tools/standard-1.0.3/
tools/standard-1.0.3/lib/ tools/standard-1.0.3/tld/ tools/struts-1.2.4/
tools/struts-1.2.4/lib/ web/ web/WEB-INF/ web/WEB-INF/classes/
web/WEB-INF/classes/flavors/ web/WEB-INF/classes/themes/ web/bookmarks/
web/editor/ web/editor/images/ web/images/ web/images/editor/
web/images/midas/ web/images/preview/ web/images/smileys/ web/planet/
web/tags/ web/templates/ web/theme/ web/theme/images/ web/theme/lavender/
web/theme/scripts/ web/theme/scripts/classes/ web/themes/ web/themes/basic/
web/themes/berkley/ web/themes/berkley/images/ web/themes/brushedmetal/
web/themes/brushedmetal/images/ web/themes/cheb/ web/themes/cheb/images/
web/themes/cheb/scripts/ web/themes/clean/ web/themes/currency-i18n/
web/themes/currency-i18n/images/ web/themes/currency/
web/themes/currency/images/ web/themes/grey2/ web/themes/moonshine/
web/themes/movablemanila/ web/themes/movablemanila/images/
web/themes/pacifica/ web/themes/robot/ web/themes/rolling/
web/themes/rolling/images/ web/themes/sotto/ web/themes/sotto/images/
web/themes/sotto/styles/ web/themes/sunsets/ web/themes/sunsets/images/
web/themes/sunsets/scripts/ web/themes/sunsets/styles/ web/themes/werner/
web/themes/x2/ web/themes/x2/images/ web/themes/x2/scripts/
web/themes/x2/styles/ web/weblog/ web/website/
Added: incubator/roller/trunk/src/org/roller/business/IndexManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/business/IndexManagerImpl.java?rev=189695&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/business/IndexManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/roller/business/IndexManagerImpl.java Wed Jun 8 20:18:46 2005
@@ -0,0 +1,387 @@
+/*
+ * 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.model.ThreadManager;
+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;
+
+/**
+ * @author aim4min
+ * @author mraible (formatting and indexDir configurable)
+ *
+ * This is the lucene manager. This is the central entry point into the Lucene
+ * searching API. This should be retrieved from the roller context, and not
+ * instatiated manually.
+ *
+ */
+public class IndexManagerImpl implements IndexManager
+{
+ //~ Static fields/initializers
+ // =============================================
+
+ private IndexReader reader;
+
+ static Log mLogger = LogFactory.getFactory().getInstance(
+ IndexManagerImpl.class);
+
+ //~ Instance fields
+ // ========================================================
+
+ private ThreadManager mThreadManager;
+
+ 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(String indexDir, ThreadManager manager)
+ {
+ this.mThreadManager = manager;
+
+ this.indexDir = indexDir;
+
+ String test = indexDir + File.separator + ".index-inconsistent";
+ indexConsistencyMarker = new File(test);
+
+ // 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));
+ }
+ }
+
+ }
+
+ //~ 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();
+ }
+
+ public void scheduleIndexOperation(final IndexOperation op)
+ {
+ try
+ {
+ mThreadManager.executeInBackground(op);
+ }
+ catch (InterruptedException e)
+ {
+ mLogger.error("Error executing operation", e);
+ }
+ }
+
+ /**
+ * @param search
+ */
+ public void executeIndexOperationNow(final IndexOperation op)
+ {
+ try
+ {
+ mThreadManager.executeInForeground(op);
+ }
+ 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/trunk/src/org/roller/business/PersistenceStrategy.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/business/PersistenceStrategy.java?rev=189695&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/business/PersistenceStrategy.java (added)
+++ incubator/roller/trunk/src/org/roller/business/PersistenceStrategy.java Wed Jun 8 20:18:46 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/trunk/src/org/roller/business/PingQueueManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/business/PingQueueManagerImpl.java?rev=189695&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/business/PingQueueManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/roller/business/PingQueueManagerImpl.java Wed Jun 8 20:18:46 2005
@@ -0,0 +1,55 @@
+/*
+ * 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;
+
+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/trunk/src/org/roller/business/PingTargetManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/business/PingTargetManagerImpl.java?rev=189695&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/business/PingTargetManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/roller/business/PingTargetManagerImpl.java Wed Jun 8 20:18:46 2005
@@ -0,0 +1,144 @@
+/*
+ * 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;
+
+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/trunk/src/org/roller/business/PlanetManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/business/PlanetManagerImpl.java?rev=189695&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/business/PlanetManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/roller/business/PlanetManagerImpl.java Wed Jun 8 20:18:46 2005
@@ -0,0 +1,244 @@
+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;
+ protected Date lastUpdated = new Date();
+ protected List aggregation = null;
+ protected Map lastUpdatedByGroup = new HashMap();
+
+ // 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);
+
+ 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);
+ }
+ 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");
+ }
+
+ public synchronized void clearCachedAggregations()
+ {
+ aggregation = null;
+ aggregationsByGroup.purge();
+ lastUpdatedByGroup.clear();
+ lastUpdated = new Date();
+ }
+
+ public Date getLastUpdated()
+ {
+ return lastUpdated;
+ }
+
+ public Date getLastUpdated(PlanetGroupData group)
+ {
+ return (Date)lastUpdatedByGroup.get(group);
+ }
+}
Added: incubator/roller/trunk/src/org/roller/business/PropertiesManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/business/PropertiesManagerImpl.java?rev=189695&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/business/PropertiesManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/roller/business/PropertiesManagerImpl.java Wed Jun 8 20:18:46 2005
@@ -0,0 +1,243 @@
+/*
+ * 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();
+
+ // 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/trunk/src/org/roller/business/PubTimeData.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/business/PubTimeData.java?rev=189695&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/business/PubTimeData.java (added)
+++ incubator/roller/trunk/src/org/roller/business/PubTimeData.java Wed Jun 8 20:18:46 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/trunk/src/org/roller/business/RefererManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/business/RefererManagerImpl.java?rev=189695&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/business/RefererManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/roller/business/RefererManagerImpl.java Wed Jun 8 20:18:46 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/trunk/src/org/roller/business/RollerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/business/RollerImpl.java?rev=189695&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/business/RollerImpl.java (added)
+++ incubator/roller/trunk/src/org/roller/business/RollerImpl.java Wed Jun 8 20:18:46 2005
@@ -0,0 +1,110 @@
+/*
+ * 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.config.RollerConfig;
+import org.roller.model.FileManager;
+import org.roller.model.IndexManager;
+import org.roller.model.Roller;
+import org.roller.model.ThreadManager;
+import org.roller.util.StringUtils;
+
+
+/**
+ * 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;
+
+
+ /** 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)
+ {
+ String indexDir = RollerConfig.getProperty("search.index.dir");
+ if (indexDir.indexOf("${user.home}") != -1)
+ {
+ indexDir = StringUtils.replace(
+ indexDir, "${user.home}",
+ System.getProperty("user.home"));
+ }
+ if (mLogger.isDebugEnabled())
+ {
+ mLogger.debug("index dir: " + indexDir);
+ }
+ mIndexManager = new IndexManagerImpl(indexDir, this.getThreadManager());
+ }
+ return mIndexManager;
+ }
+
+
+ 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/trunk/src/org/roller/business/ThreadManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/business/ThreadManagerImpl.java?rev=189695&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/business/ThreadManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/roller/business/ThreadManagerImpl.java Wed Jun 8 20:18:46 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
Added: incubator/roller/trunk/src/org/roller/business/UserManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/business/UserManagerImpl.java?rev=189695&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/business/UserManagerImpl.java (added)
+++ incubator/roller/trunk/src/org/roller/business/UserManagerImpl.java Wed Jun 8 20:18:46 2005
@@ -0,0 +1,418 @@
+/*
+ * Created on Aug 13, 2003
+ */
+package org.roller.business;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.RollerException;
+import org.roller.model.BookmarkManager;
+import org.roller.model.Roller;
+import org.roller.model.UserManager;
+import org.roller.model.WeblogManager;
+import org.roller.pojos.BookmarkData;
+import org.roller.pojos.FolderData;
+import org.roller.pojos.PageData;
+import org.roller.pojos.RoleData;
+import org.roller.pojos.UserCookieData;
+import org.roller.pojos.UserData;
+import org.roller.pojos.WeblogCategoryData;
+import org.roller.pojos.WebsiteData;
+import org.roller.util.RandomGUID;
+import org.roller.util.Utilities;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.roller.model.RollerFactory;
+
+/**
+ * Abstract base implementation using PersistenceStrategy.
+ * @author Dave Johnson
+ * @author Lance Lavandowska
+ */
+public abstract class UserManagerImpl implements UserManager
+{
+ protected PersistenceStrategy mStrategy;
+
+ private static Log mLogger =
+ LogFactory.getFactory().getInstance(UserManagerImpl.class);
+
+ public UserManagerImpl(PersistenceStrategy strategy)
+ {
+ mStrategy = strategy;
+ }
+
+ public void release()
+ {
+ }
+
+ //--------------------------------------------------------------- Website
+
+ public WebsiteData retrieveWebsite(String id) throws RollerException
+ {
+ return (WebsiteData)mStrategy.load(id,WebsiteData.class);
+ }
+
+ /**
+ * @see org.roller.model.UserManager#storeWebsite(org.roller.pojos.WebsiteData)
+ */
+ public void storeWebsite(WebsiteData data) throws RollerException
+ {
+ mStrategy.store(data);
+ }
+
+ public void removeWebsite(String id) throws RollerException
+ {
+ mStrategy.remove(id,WebsiteData.class);
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ /**
+ * This method is a hotspot, it is called on every page request.
+ */
+ public WebsiteData getWebsite(String userName) throws RollerException
+ {
+ return getWebsite(userName, true);
+ }
+
+ //------------------------------------------------------------------- User
+
+ public UserData retrieveUser(String id) throws RollerException
+ {
+ return (UserData)mStrategy.load(id,UserData.class);
+ }
+
+ public void storeUser(UserData data) throws RollerException
+ {
+ mStrategy.store(data);
+ }
+
+ public void removeUser(String id) throws RollerException
+ {
+ mStrategy.remove(id,UserData.class);
+ }
+
+ //-----------------------------------------------------------------------
+
+ public UserData getUser(String userName) throws RollerException
+ {
+ return getUser(userName, true);
+ }
+
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ public UserData getUser(String userName, boolean enabledOnly) throws RollerException
+ {
+ if (userName==null )
+ throw new RollerException("userName is null");
+
+ WebsiteData website = getWebsite(userName, enabledOnly);
+ if (website != null)
+ {
+ return website.getUser();
+ }
+ return null;
+ }
+
+ //-----------------------------------------------------------------------
+
+ public List getUsers() throws RollerException
+ {
+ return getUsers(true);
+ }
+
+ //------------------------------------------------------------------------
+ /**
+ * @see org.roller.model.UserManager#retrievePage(java.lang.String)
+ */
+ public PageData retrievePageReadOnly(String id) throws RollerException
+ {
+ // Don't hit database for templates stored on disk
+ if (id != null && id.endsWith(".vm")) return null;
+
+ // Hibernate has a read-only flag: LockMode.READ
+ return (PageData)mStrategy.load(id,PageData.class);
+ }
+
+ //------------------------------------------------------------------- Role
+
+ public RoleData retrieveRole(String id) throws RollerException
+ {
+ return (RoleData)mStrategy.load(id,RoleData.class);
+ }
+
+ public void storeRole(RoleData data) throws RollerException
+ {
+ mStrategy.store(data);
+ }
+
+ public void removeRole(String id) throws RollerException
+ {
+ mStrategy.remove(id,RoleData.class);
+ }
+
+ //------------------------------------------------------------------- Page
+
+ public PageData retrievePage(String id) throws RollerException
+ {
+ // Don't hit database for templates stored on disk
+ if (id != null && id.endsWith(".vm")) return null;
+
+ return (PageData)mStrategy.load(id,PageData.class);
+ }
+
+ public void removePage(String id) throws RollerException
+ {
+ mStrategy.remove(id,PageData.class);
+ }
+
+ public void removePageSafely(String id) throws RollerException
+ {
+ PageData pd = retrievePageReadOnly(id);
+ if (pd == null) return;
+
+ WebsiteData wd = pd.getWebsite();
+ if (pd.getId() == wd.getDefaultPageId()) {
+ mLogger.error("Refusing to remove default page from website of: " + wd.getUser().getUserName());
+ throw new RollerException(new IllegalArgumentException("Page is default page of website."));
+ }
+ removePage(id);
+ }
+
+ /**
+ * @see org.roller.model.UserManager#storePage(org.roller.pojos.PageData)
+ */
+ public void storePage(PageData data) throws RollerException
+ {
+ mStrategy.store(data);
+ }
+
+ public String fixPageLink(PageData data) throws RollerException
+ {
+ String link = Utilities.removeHTML(data.getName());
+ link = Utilities.removeNonAlphanumeric(link);
+
+ data.setLink(link);
+ mStrategy.store( data );
+
+ return link;
+ }
+
+ /**
+ * Add a new Roller user. Store new User, Role, Website, Category, and a
+ * "first post" WeblogEntry in the database. Reads in files from a theme
+ * directory and adds them as Pages for the User's new Website.
+ *
+ * @param ud User object representing the new user.
+ * @param themeDir Directory containing the theme for this user
+ */
+ public void addUser(UserData ud, Map pages, String theme,
+ String locale, String timezone)
+ throws RollerException
+ {
+ Roller mRoller = RollerFactory.getRoller();
+ UserManager umgr = mRoller.getUserManager();
+ WeblogManager wmgr = mRoller.getWeblogManager();
+ if ( umgr.getUser(ud.getUserName()) != null
+ || umgr.getUser(ud.getUserName().toLowerCase()) != null)
+ {
+ throw new RollerException("error.add.user.userNameInUse");
+ }
+
+ boolean adminUser = false;
+ List users = this.getUsers();
+ if (users.size() == 0)
+ {
+ // Make first user an admin
+ adminUser = true;
+ }
+
+ mStrategy.store(ud);
+
+ RoleData rd = new RoleData(null, ud, "editor");
+ mStrategy.store(rd);
+
+ //
+ // CREATE WEBSITE AND CATEGORIES FOR USER
+ //
+
+ WebsiteData website = new WebsiteData(null,
+ ud.getFullName()+"'s Weblog", // name
+ ud.getFullName()+"'s Weblog", // description
+ ud, // userId
+ "dummy", // defaultPageId
+ "dummy", // weblogDayPageId
+ Boolean.TRUE, // enableBloggerApi
+ null, // bloggerCategory
+ null, // defaultCategory
+ "editor-text.jsp", // editorPage
+ "", // ignoreWords
+ Boolean.TRUE, // allowComments
+ Boolean.FALSE, // emailComments
+ "", // emailFromAddress
+ Boolean.TRUE); // isEnabled
+ website.setEditorTheme(theme);
+ website.setLocale(locale);
+ website.setTimezone(timezone);
+ website.save();
+
+ WeblogCategoryData rootCat = wmgr.createWeblogCategory(
+ website, // websiteId
+ null, // parent
+ "root", // name
+ "root", // description
+ null ); // image
+ rootCat.save();
+
+ WeblogCategoryData generalCat = wmgr.createWeblogCategory(
+ website, // websiteId
+ rootCat,
+ "General", // name
+ "General", // description
+ null ); // image
+ generalCat.save();
+
+ WeblogCategoryData javaCat = wmgr.createWeblogCategory(
+ website, // websiteId
+ rootCat,
+ "Java", // name
+ "Java", // description
+ null ); // image
+ javaCat.save();
+
+ WeblogCategoryData musicCat = wmgr.createWeblogCategory(
+ website, // websiteId
+ rootCat,
+ "Music", // name
+ "Music", // description
+ null ); // image
+ musicCat.save();
+
+ website.setBloggerCategory(rootCat);
+ website.setDefaultCategory(rootCat);
+
+ Integer zero = new Integer(0);
+
+ BookmarkManager bmgr = mRoller.getBookmarkManager();
+
+ FolderData root = bmgr.createFolder(
+ null, "root", "root", website);
+ root.save();
+
+ FolderData blogroll = bmgr.createFolder(
+ root, "Blogroll", "Blogroll", website);
+ blogroll.save();
+
+ BookmarkData b1 = bmgr.createBookmark(
+ blogroll, "Dave Johnson", "",
+ "http://rollerweblogger.org/page/roller",
+ "http://rollerweblogger.org/rss/roller",
+ zero, zero, null);
+ b1.save();
+
+ BookmarkData b2 = bmgr.createBookmark(
+ blogroll, "Matt Raible", "",
+ "http://raibledesigns.com/page/rd",
+ "http://raibledesigns.com/rss/rd",
+ zero, zero, null);
+ b2.save();
+
+ BookmarkData b3 = bmgr.createBookmark(
+ blogroll, "Lance Lavandowska", "",
+ "http://brainopolis.dnsalias.com/roller/page/lance/",
+ "http://brainopolis.dnsalias.com/roller/rss/lance/",
+ zero, zero, null);
+ b3.save();
+
+
+ FolderData news = bmgr.createFolder(
+ root, "News", "News", website);
+ news.save();
+
+ BookmarkData b5 = bmgr.createBookmark(
+ news, "CNN", "",
+ "http://www.cnn.com",
+ "",
+ zero, zero, null);
+ b5.save();
+
+ BookmarkData b6 = bmgr.createBookmark(
+ news, "NY Times", "",
+ "http://nytimes.com",
+ "",
+ zero, zero, null);
+ b6.save();
+
+ //
+ // READ THEME FILES AND CREATE PAGES FOR USER
+ //
+ Iterator iter = pages.keySet().iterator();
+ while ( iter.hasNext() )
+ {
+ String pageName = (String) iter.next();
+ String sb = (String)pages.get( pageName );
+
+ // Store each Velocity template as a page
+ PageData pd = new PageData( null,
+ website, // website
+ pageName, // name
+ pageName, // description
+ pageName, // link
+ sb, // template
+ new Date() // updateTime
+ );
+ mStrategy.store(pd);
+
+ if ( pd.getName().equals("Weblog") )
+ {
+ website.setDefaultPageId(pd.getId());
+ }
+ else if ( pd.getName().equals("_day") )
+ {
+ website.setWeblogDayPageId(pd.getId());
+ }
+ }
+
+ if (adminUser) ud.grantRole("admin");
+
+ // Save website with blogger cat id, defauld page id and day id
+ mStrategy.store(website);
+ }
+
+ /**
+ * @see org.roller.model.UserManager#createLoginCookie(java.lang.String)
+ */
+ public String createLoginCookie(String username) throws RollerException
+ {
+ UserCookieData cookie = new UserCookieData();
+ cookie.setUsername(username);
+
+ return saveLoginCookie(cookie);
+ }
+
+ /**
+ * Convenience method to set a unique cookie id and save to database
+ *
+ * @param cookie
+ * @return
+ * @throws Exception
+ */
+ protected String saveLoginCookie(UserCookieData cookie) throws RollerException
+ {
+ cookie.setCookieId(new RandomGUID().toString());
+ cookie.save();
+
+ String cookieString = null;
+ try {
+ cookieString = Utilities.encodeString(cookie.getUsername() + "|" +
+ cookie.getCookieId());
+ } catch (IOException io) {
+ mLogger.warn("Failed to encode rememberMe cookieString");
+ mLogger.warn(io.getMessage());
+ cookieString = cookie.getUsername() + "|" + cookie.getCookieId();
+ }
+ return cookieString;
+ }
+}