husted 2004/03/25 04:41:51 Added: chain/apps/mailreader/src/java/org/apache/struts/webapp/example/memory MemoryDatabasePlugIn.java MemorySubscription.java MemoryUser.java MemoryUserDatabase.java TestUserDatabase.java Log: Initial import of MailReader Example application for Commons Chain Revision Changes Path 1.1 jakarta-commons-sandbox/chain/apps/mailreader/src/java/org/apache/struts/webapp/example/memory/MemoryDatabasePlugIn.java Index: MemoryDatabasePlugIn.java =================================================================== /* * $Header: /home/cvs/jakarta-commons-sandbox/chain/apps/mailreader/src/java/org/apache/struts/webapp/example/memory/MemoryDatabasePlugIn.java,v 1.1 2004/03/25 12:41:51 husted Exp $ * $Revision: 1.1 $ * $Date: 2004/03/25 12:41:51 $ * * Copyright 2000-2004 Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.struts.webapp.example.memory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.action.ActionServlet; import org.apache.struts.action.PlugIn; import org.apache.struts.config.ModuleConfig; import org.apache.struts.webapp.example.Constants; import javax.servlet.ServletException; import java.io.*; /** * <p><strong>MemoryDatabasePlugIn</strong> initializes and finalizes the * persistent storage of User and Subscription information for the Struts * Demonstration Application, using an in-memory database backed by an * XML file.</p> * * <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run * from a WAR file, or in another environment where reading and writing of the * web application resource is impossible, the initial contents will be copied * to a file in the web application temporary directory provided by the * container. This is for demonstration purposes only - you should * <strong>NOT</strong> assume that files written here will survive a restart * of your servlet container.</p> * * @version $Revision: 1.1 $ $Date: 2004/03/25 12:41:51 $ */ public final class MemoryDatabasePlugIn implements PlugIn { // ----------------------------------------------------- Instance Variables /** * The [EMAIL PROTECTED] MemoryUserDatabase} object we construct and make available. */ private MemoryUserDatabase database = null; /** * Logging output for this plug in instance. */ private Log log = LogFactory.getLog(this.getClass()); /** * The [EMAIL PROTECTED] ActionServlet} owning this application. */ private ActionServlet servlet = null; // ------------------------------------------------------------- Properties /** * The web application resource path of our persistent database * storage file. */ private String pathname = "/WEB-INF/database.xml"; public String getPathname() { return (this.pathname); } public void setPathname(String pathname) { this.pathname = pathname; } // --------------------------------------------------------- PlugIn Methods /** * Gracefully shut down this database, releasing any resources * that were allocated at initialization. */ public void destroy() { log.info("Finalizing memory database plug in"); if (database != null) { try { database.close(); } catch (Exception e) { log.error("Closing memory database", e); } } servlet.getServletContext().removeAttribute(Constants.DATABASE_KEY); database = null; servlet = null; database = null; } /** * Initialize and load our initial database from persistent storage. * * @param servlet The ActionServlet for this web application * @param config The ApplicationConfig for our owning module * * @exception ServletException if we cannot configure ourselves correctly */ public void init(ActionServlet servlet, ModuleConfig config) throws ServletException { log.info("Initializing memory database plug in from '" + pathname + "'"); // Remember our associated configuration and servlet this.servlet = servlet; // Construct a new database and make it available database = new MemoryUserDatabase(); try { String path = calculatePath(); if (log.isDebugEnabled()) { log.debug(" Loading database from '" + path + "'"); } database.setPathname(path); database.open(); } catch (Exception e) { log.error("Opening memory database", e); throw new ServletException("Cannot load database from '" + pathname + "'", e); } // Make the initialized database available servlet.getServletContext().setAttribute(Constants.DATABASE_KEY, database); } // --------------------------------------------------------- Public Methods // ------------------------------------------------------ Protected Methods // -------------------------------------------------------- Private Methods /** * Calculate and return an absolute pathname to the XML file to contain * our persistent storage information. * * @exception Exception if an input/output error occurs */ private String calculatePath() throws Exception { // Can we access the database via file I/O? String path = servlet.getServletContext().getRealPath(pathname); if (path != null) { return (path); } // Does a copy of this file already exist in our temporary directory File dir = (File) servlet.getServletContext().getAttribute ("javax.servlet.context.tempdir"); File file = new File(dir, "struts-example-database.xml"); if (file.exists()) { return (file.getAbsolutePath()); } // Copy the static resource to a temporary file and return its path InputStream is = servlet.getServletContext().getResourceAsStream(pathname); BufferedInputStream bis = new BufferedInputStream(is, 1024); FileOutputStream os = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(os, 1024); byte buffer[] = new byte[1024]; while (true) { int n = bis.read(buffer); if (n <= 0) { break; } bos.write(buffer, 0, n); } bos.close(); bis.close(); return (file.getAbsolutePath()); } } 1.1 jakarta-commons-sandbox/chain/apps/mailreader/src/java/org/apache/struts/webapp/example/memory/MemorySubscription.java Index: MemorySubscription.java =================================================================== /* * $Header: /home/cvs/jakarta-commons-sandbox/chain/apps/mailreader/src/java/org/apache/struts/webapp/example/memory/MemorySubscription.java,v 1.1 2004/03/25 12:41:51 husted Exp $ * $Revision: 1.1 $ * $Date: 2004/03/25 12:41:51 $ * * Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.struts.webapp.example.memory; import org.apache.struts.webapp.example.Subscription; import org.apache.struts.webapp.example.User; /** * <p>Concrete implementation of [EMAIL PROTECTED] Subscription} for an in-memory * database backed by an XML data file.</p> * * @version $Revision: 1.1 $ $Date: 2004/03/25 12:41:51 $ * @since Struts 1.1 */ public final class MemorySubscription implements Subscription { // ----------------------------------------------------------- Constructors /** * <p>Construct a new Subscription associated with the specified * [EMAIL PROTECTED] User}. * * @param user The user with which we are associated * @param host The mail host for this subscription */ public MemorySubscription(MemoryUser user, String host) { super(); this.user = user; this.host = host; } // ----------------------------------------------------- Instance Variables /** * The mail host for this subscription. */ private String host = null; /** * The [EMAIL PROTECTED] User} with which we are associated. */ private MemoryUser user = null; // ------------------------------------------------------------- Properties /** * Should we auto-connect at startup time? */ private boolean autoConnect = false; public boolean getAutoConnect() { return (this.autoConnect); } public void setAutoConnect(boolean autoConnect) { this.autoConnect = autoConnect; } /** * The mail host for this subscription. */ public String getHost() { return (this.host); } /** * The password (in clear text) for this subscription. */ private String password = null; public String getPassword() { return (this.password); } public void setPassword(String password) { this.password = password; } /** * The subscription type ("imap" or "pop3"). */ private String type = "imap"; public String getType() { return (this.type); } public void setType(String type) { this.type = type; } /** * The User owning this Subscription. */ public User getUser() { return (this.user); } /** * The username for this subscription. */ private String username = null; public String getUsername() { return (this.username); } public void setUsername(String username) { this.username = username; } // --------------------------------------------------------- Public Methods /** * Return a String representation of this object. */ public String toString() { StringBuffer sb = new StringBuffer("<subscription host=\""); sb.append(host); sb.append("\" autoConnect=\""); sb.append(autoConnect); sb.append("\""); if (password != null) { sb.append(" password=\""); sb.append(password); sb.append("\""); } if (type != null) { sb.append(" type=\""); sb.append(type); sb.append("\""); } if (username != null) { sb.append(" username=\""); sb.append(username); sb.append("\""); } sb.append(">"); return (sb.toString()); } } 1.1 jakarta-commons-sandbox/chain/apps/mailreader/src/java/org/apache/struts/webapp/example/memory/MemoryUser.java Index: MemoryUser.java =================================================================== /* * $Header: /home/cvs/jakarta-commons-sandbox/chain/apps/mailreader/src/java/org/apache/struts/webapp/example/memory/MemoryUser.java,v 1.1 2004/03/25 12:41:51 husted Exp $ * $Revision: 1.1 $ * $Date: 2004/03/25 12:41:51 $ * * Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.struts.webapp.example.memory; import org.apache.struts.webapp.example.Subscription; import org.apache.struts.webapp.example.User; import org.apache.struts.webapp.example.UserDatabase; import java.util.HashMap; /** * <p>Concrete implementation of [EMAIL PROTECTED] User} for an in-memory * database backed by an XML data file.</p> * * @version $Revision: 1.1 $ $Date: 2004/03/25 12:41:51 $ * @since Struts 1.1 */ public final class MemoryUser implements User { // ----------------------------------------------------------- Constructors /** * <p>Construct a new User associated with the specified * [EMAIL PROTECTED] UserDatabase}. * * @param database The user database with which we are associated * @param username The username of this user */ public MemoryUser(MemoryUserDatabase database, String username) { super(); this.database = database; this.username = username; } // ----------------------------------------------------- Instance Variables /** * The [EMAIL PROTECTED] UserDatabase} with which we are associated. */ private MemoryUserDatabase database = null; /** * The [EMAIL PROTECTED] Subscription}s for this User, keyed by hostname. */ private HashMap subscriptions = new HashMap(); /** * The username for this user. */ private String username = null; // ------------------------------------------------------------- Properties /** * The [EMAIL PROTECTED] UserDatabase} with which we are associated. */ public UserDatabase getDatabase() { return (this.database); } /** * The email address from which messages are sent. */ private String fromAddress = null; public String getFromAddress() { return (this.fromAddress); } public void setFromAddress(String fromAddress) { this.fromAddress = fromAddress; } /** * The full name of this user, included in from addresses. */ private String fullName = null; public String getFullName() { return (this.fullName); } public void setFullName(String fullName) { this.fullName = fullName; } /** * The password (in clear text). */ private String password = null; public String getPassword() { return (this.password); } public void setPassword(String password) { this.password = password; } /** * The EMAIL address to which replies should be sent. */ private String replyToAddress = null; public String getReplyToAddress() { return (this.replyToAddress); } public void setReplyToAddress(String replyToAddress) { this.replyToAddress = replyToAddress; } /** * Find and return all [EMAIL PROTECTED] Subscription}s associated with this user. * If there are none, a zero-length array is returned. */ public Subscription[] getSubscriptions() { synchronized (subscriptions) { Subscription results[] = new Subscription[subscriptions.size()]; return ((Subscription[]) subscriptions.values().toArray(results)); } } /** * The username (must be unique). */ public String getUsername() { return (this.username); } // --------------------------------------------------------- Public Methods /** * Create and return a new [EMAIL PROTECTED] Subscription} associated with this * User, for the specified host name. * * @param host Host name for which to create a subscription * * @exception IllegalArgumentException if the host name is not unique * for this user */ public Subscription createSubscription(String host) { synchronized (subscriptions) { if (subscriptions.get(host) != null) { throw new IllegalArgumentException("Duplicate host '" + host + "' for user '" + username + "'"); } MemorySubscription subscription = new MemorySubscription(this, host); synchronized (subscriptions) { subscriptions.put(host, subscription); } return (subscription); } } /** * Find and return the [EMAIL PROTECTED] Subscription} associated with the specified * host. If none is found, return <code>null</code>. * * @param host Host name to look up */ public Subscription findSubscription(String host) { synchronized (subscriptions) { return ((Subscription) subscriptions.get(host)); } } /** * Remove the specified [EMAIL PROTECTED] Subscription} from being associated * with this User. * * @param subscription Subscription to be removed * * @exception IllegalArgumentException if the specified subscription is not * associated with this User */ public void removeSubscription(Subscription subscription) { if (!(this == subscription.getUser())) { throw new IllegalArgumentException ("Subscription not associated with this user"); } synchronized (subscriptions) { subscriptions.remove(subscription.getHost()); } } /** * Return a String representation of this object. */ public String toString() { StringBuffer sb = new StringBuffer("<user username=\""); sb.append(username); sb.append("\""); if (fromAddress != null) { sb.append(" fromAddress=\""); sb.append(fromAddress); sb.append("\""); } if (fullName != null) { sb.append(" fullName=\""); sb.append(fullName); sb.append("\""); } if (password != null) { sb.append(" password=\""); sb.append(password); sb.append("\""); } if (replyToAddress != null) { sb.append(" replyToAddress=\""); sb.append(replyToAddress); sb.append("\""); } sb.append(">"); return (sb.toString()); } } 1.1 jakarta-commons-sandbox/chain/apps/mailreader/src/java/org/apache/struts/webapp/example/memory/MemoryUserDatabase.java Index: MemoryUserDatabase.java =================================================================== /* * $Header: /home/cvs/jakarta-commons-sandbox/chain/apps/mailreader/src/java/org/apache/struts/webapp/example/memory/MemoryUserDatabase.java,v 1.1 2004/03/25 12:41:51 husted Exp $ * $Revision: 1.1 $ * $Date: 2004/03/25 12:41:51 $ * * Copyright 2000-2004 Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.struts.webapp.example.memory; import org.apache.commons.digester.Digester; import org.apache.commons.digester.ObjectCreationFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.webapp.example.ExpiredPasswordException; import org.apache.struts.webapp.example.Subscription; import org.apache.struts.webapp.example.User; import org.apache.struts.webapp.example.UserDatabase; import org.xml.sax.Attributes; import java.io.*; import java.util.HashMap; /** * <p>Concrete implementation of [EMAIL PROTECTED] UserDatabase} for an in-memory * database backed by an XML data file.</p> * * @version $Revision: 1.1 $ $Date: 2004/03/25 12:41:51 $ * @since Struts 1.1 */ public class MemoryUserDatabase implements UserDatabase { // ----------------------------------------------------------- Constructors // ----------------------------------------------------- Instance Variables /** * Logging output for this user database instance. */ private Log log = LogFactory.getLog(this.getClass()); /** * The [EMAIL PROTECTED] User}s associated with this UserDatabase, keyed by username. */ private HashMap users = new HashMap(); // ------------------------------------------------------------- Properties /** * Absolute pathname to the persistent file we use for loading and storing * persistent data. */ private String pathname = null; private String pathnameOld = null; private String pathnameNew = null; public String getPathname() { return (this.pathname); } public void setPathname(String pathname) { this.pathname = pathname; pathnameOld = pathname + ".old"; pathnameNew = pathname + ".new"; } // --------------------------------------------------------- Public Methods // See interface for Javadoc public void close() throws Exception { save(); } // See interface for Javadoc public User createUser(String username) { synchronized (users) { if (users.get(username) != null) { throw new IllegalArgumentException("Duplicate user '" + username + "'"); } if (log.isTraceEnabled()) { log.trace("Creating user '" + username + "'"); } MemoryUser user = new MemoryUser(this, username); synchronized (users) { users.put(username, user); } return (user); } } // See interface for Javadoc public User findUser(String username) throws ExpiredPasswordException { synchronized (users) { return ((User) users.get(username)); } } // See interface for Javadoc public User[] findUsers() { synchronized (users) { User results[] = new User[users.size()]; return ((User[]) users.values().toArray(results)); } } // See interface for Javadoc public void open() throws Exception { FileInputStream fis = null; BufferedInputStream bis = null; try { // Acquire an input stream to our database file if (log.isDebugEnabled()) { log.debug("Loading database from '" + pathname + "'"); } fis = new FileInputStream(pathname); bis = new BufferedInputStream(fis); // Construct a digester to use for parsing Digester digester = new Digester(); digester.push(this); digester.setValidating(false); digester.addFactoryCreate ("database/user", new MemoryUserCreationFactory(this)); digester.addFactoryCreate ("database/user/subscription", new MemorySubscriptionCreationFactory()); // Parse the input stream to initialize our database digester.parse(bis); bis.close(); bis = null; fis = null; } catch (Exception e) { log.error("Loading database from '" + pathname + "':", e); throw e; } finally { if (bis != null) { try { bis.close(); } catch (Throwable t) { ; } bis = null; fis = null; } } } // See interface for Javadoc public void removeUser(User user) { if (!(this == user.getDatabase())) { throw new IllegalArgumentException ("User not associated with this database"); } if (log.isTraceEnabled()) { log.trace("Removing user '" + user.getUsername() + "'"); } synchronized (users) { users.remove(user.getUsername()); } } // See interface for Javadoc public void save() throws Exception { if (log.isDebugEnabled()) { log.debug("Saving database to '" + pathname + "'"); } File fileNew = new File(pathnameNew); PrintWriter writer = null; try { // Configure our PrintWriter FileOutputStream fos = new FileOutputStream(fileNew); OutputStreamWriter osw = new OutputStreamWriter(fos); writer = new PrintWriter(osw); // Print the file prolog writer.println("<?xml version='1.0'?>"); writer.println("<database>"); // Print entries for each defined user and associated subscriptions User users[] = findUsers(); for (int i = 0; i < users.length; i++) { writer.print(" "); writer.println(users[i]); Subscription subscriptions[] = users[i].getSubscriptions(); for (int j = 0; j < subscriptions.length; j++) { writer.print(" "); writer.println(subscriptions[j]); writer.print(" "); writer.println("</subscription>"); } writer.print(" "); writer.println("</user>"); } // Print the file epilog writer.println("</database>"); // Check for errors that occurred while printing if (writer.checkError()) { writer.close(); fileNew.delete(); throw new IOException ("Saving database to '" + pathname + "'"); } writer.close(); writer = null; } catch (IOException e) { if (writer != null) { writer.close(); } fileNew.delete(); throw e; } // Perform the required renames to permanently save this file File fileOrig = new File(pathname); File fileOld = new File(pathnameOld); if (fileOrig.exists()) { fileOld.delete(); if (!fileOrig.renameTo(fileOld)) { throw new IOException ("Renaming '" + pathname + "' to '" + pathnameOld + "'"); } } if (!fileNew.renameTo(fileOrig)) { if (fileOld.exists()) { fileOld.renameTo(fileOrig); } throw new IOException ("Renaming '" + pathnameNew + "' to '" + pathname + "'"); } fileOld.delete(); } } /** * Digester object creation factory for subscription instances. */ class MemorySubscriptionCreationFactory implements ObjectCreationFactory { private Digester digester = null; public Digester getDigester() { return (this.digester); } public void setDigester(Digester digester) { this.digester = digester; } public Object createObject(Attributes attributes) { String host = attributes.getValue("host"); User user = (User) digester.peek(); Subscription subscription = user.createSubscription(host); String autoConnect = attributes.getValue("autoConnect"); if (autoConnect == null) { autoConnect = "false"; } if ("true".equalsIgnoreCase(autoConnect) || "yes".equalsIgnoreCase(autoConnect)) { subscription.setAutoConnect(true); } else { subscription.setAutoConnect(false); } subscription.setPassword(attributes.getValue("password")); subscription.setType(attributes.getValue("type")); subscription.setUsername(attributes.getValue("username")); return (subscription); } } /** * Digester object creation factory for user instances. */ class MemoryUserCreationFactory implements ObjectCreationFactory { public MemoryUserCreationFactory(MemoryUserDatabase database) { this.database = database; } private MemoryUserDatabase database = null; private Digester digester = null; public Digester getDigester() { return (this.digester); } public void setDigester(Digester digester) { this.digester = digester; } public Object createObject(Attributes attributes) { String username = attributes.getValue("username"); User user = database.createUser(username); user.setFromAddress(attributes.getValue("fromAddress")); user.setFullName(attributes.getValue("fullName")); user.setPassword(attributes.getValue("password")); user.setReplyToAddress(attributes.getValue("replyToAddress")); return (user); } } 1.1 jakarta-commons-sandbox/chain/apps/mailreader/src/java/org/apache/struts/webapp/example/memory/TestUserDatabase.java Index: TestUserDatabase.java =================================================================== /* * Copyright 1999-2002,2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.struts.webapp.example.memory; import org.apache.struts.webapp.example.ExpiredPasswordException; import org.apache.struts.webapp.example.User; /** * <p>Help test exception handling by throwing exceptions when "magic" user names are requested.</p> */ public final class TestUserDatabase extends MemoryUserDatabase { /** * If the username is "expired" throw an ExpiredPasswordException * to simulate a business exception. * If the username is "arithmetic" throw an Aritmetic exception to * simulate a system exception. * Otherwise, delegate to MemoryDatabase. * @param username * @return */ public User findUser(String username) throws ExpiredPasswordException { if ("expired".equals(username)) throw new ExpiredPasswordException("Testing ExpiredPasswordException ..."); if ("arithmetic".equals(username)) throw new ArithmeticException(); return super.findUser(username); } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]