diff --git a/ccm-core/src/main/java/com/arsdigita/mail/Mail.java b/ccm-core/src/main/java/com/arsdigita/mail/Mail.java index e5c0e2955..f6f9f90df 100644 --- a/ccm-core/src/main/java/com/arsdigita/mail/Mail.java +++ b/ccm-core/src/main/java/com/arsdigita/mail/Mail.java @@ -52,21 +52,22 @@ import java.util.Iterator; import java.util.Set; /** - * Represents a email message with optional attachments. This class - * is a wrapper for the JavaMail API that makes it easier for - * application developers to create and send email. For simple plain - * text message, there is a static convenience method that does not - * require the construction of an explicit Mail object: + * Represents a email message with optional attachments. This class is a wrapper + * for the JavaMail API that makes it easier for application developers to + * create and send email. For simple plain text message, there is a static + * convenience method that does not require the construction of an explicit Mail + * object: * *
  * Mail.send(to, from, subject, body)
  * 
* - *

For more complex messages, the API provides methods to set all - * standard mail headers, attach other pieces of content, and finally - * invoke the transport process to deliver the message. + *

+ * For more complex messages, the API provides methods to set all standard mail + * headers, attach other pieces of content, and finally invoke the transport + * process to deliver the message. * - * @author Ron Henderson + * @author Ron Henderson * @version $Id$ */ public class Mail implements MessageType { @@ -74,11 +75,10 @@ public class Mail implements MessageType { /** * Used for logging. */ - private static final Logger s_log = - Logger.getLogger(Mail.class); + private static final Logger s_log = Logger.getLogger(Mail.class); - private static final InternetAddress[] EMPTY_ADDRESS_LIST = - new InternetAddress[0]; + private static final InternetAddress[] EMPTY_ADDRESS_LIST + = new InternetAddress[0]; /** * Table of message headers. */ @@ -90,11 +90,13 @@ public class Mail implements MessageType { private InternetAddress[] m_filteredTo = EMPTY_ADDRESS_LIST; private InternetAddress[] m_invalidTo = EMPTY_ADDRESS_LIST; private static Set s_invalidDomains = new HashSet(); + static { s_log.debug("Static initalizer starting..."); s_invalidDomains.add("example.com"); s_log.debug("Static initalizer finished."); } + /** * Email address the message is being sent from. */ @@ -124,8 +126,8 @@ public class Mail implements MessageType { */ private String m_alternate; /** - * Encoding specification for m_body and m_alternate (optional). - * Default value (null) implies "us-ascii" encoding. + * Encoding specification for m_body and m_alternate (optional). Default + * value (null) implies "us-ascii" encoding. */ private String m_encoding; /** @@ -141,13 +143,13 @@ public class Mail implements MessageType { */ private static Session s_session; /** - * SMTP host to connect to. Only used to override the default for - * testing purposes. + * SMTP host to connect to. Only used to override the default for testing + * purposes. */ private static String s_host; /** - * SMTP port to connect to. Only used to override the default for - * testing purposes. + * SMTP port to connect to. Only used to override the default for testing + * purposes. */ private static String s_port; // Constants used by Mail @@ -165,8 +167,8 @@ public class Mail implements MessageType { public final static String ATTACHMENT = javax.mail.Part.ATTACHMENT; /** - * Default constructor. Must use the setTo, setSubject (and so on) - * methods to create a valid mail message. + * Default constructor. Must use the setTo, setSubject (and so on) methods + * to create a valid mail message. */ public Mail() { this(null, null, null, null); @@ -175,8 +177,8 @@ public class Mail implements MessageType { /** * Constructor used to specify to, from, and subject. * - * @param to one or more of addresses to send the message to - * @param from the address the message is being sent from + * @param to one or more of addresses to send the message to + * @param from the address the message is being sent from * @param subject the subject for the message */ public Mail(String to, @@ -188,10 +190,10 @@ public class Mail implements MessageType { /** * Constructor used to specify to, from, subject, and body. * - * @param to one or more of addresses to send the message to - * @param from the address the message is being sent from + * @param to one or more of addresses to send the message to + * @param from the address the message is being sent from * @param subject the subject for the message - * @param body the plain text body of the message + * @param body the plain text body of the message */ public Mail(String to, String from, @@ -205,14 +207,13 @@ public class Mail implements MessageType { } /** - * Constructor used to specify to, from, subject, body, and - * encoding. + * Constructor used to specify to, from, subject, body, and encoding. * - * @param to one or more of addresses to send the message to - * @param from the address the message is being sent from + * @param to one or more of addresses to send the message to + * @param from the address the message is being sent from * @param subject the subject for the message - * @param body is plain text body of the message - * @param enc the encoding of the body + * @param body is plain text body of the message + * @param enc the encoding of the body */ public Mail(String to, String from, @@ -226,45 +227,48 @@ public class Mail implements MessageType { /** * A convenience method to send a simple plain-text message. * - * @param to one or more of addresses to send the message to - * @param from the address the message is being sent from + * @param to one or more of addresses to send the message to + * @param from the address the message is being sent from * @param subject the subject for the message - * @param body the plain text body of the message + * @param body the plain text body of the message */ public static void send(String to, String from, String subject, String body) - throws MessagingException, - SendFailedException { + throws MessagingException, + SendFailedException { Mail msg = new Mail(to, from, subject, body); msg.send(); } - + /** * Sends the message. */ public void send() - throws MessagingException, - SendFailedException { + throws MessagingException, + SendFailedException { + final Properties properties = MailConfig.getConfig().getJavaMailProperties(); Transport transport = getSession().getTransport(); - transport.connect(); + transport.connect(properties.getProperty("mail.smtp.user"), + properties.getProperty("mail.smtp.password")); send(transport); transport.close(); } /** - * Sends the message using a given Transport object (package-level - * access). This method is used when sending multiple messages at - * once with a single connection to the mail server. + * Sends the message using a given Transport object (package-level access). + * This method is used when sending multiple messages at once with a single + * connection to the mail server. * - * @throws SendFailedException on any kind of MessagingException, - * also such returned from the server. Applications might try - * to catch this and re-schedule sending the mail. + * @throws SendFailedException on any kind of MessagingException, also such + * returned from the server. Applications might + * try to catch this and re-schedule sending the + * mail. */ void send(Transport transport) - throws MessagingException, - SendFailedException { + throws MessagingException, + SendFailedException { Message msg = null; if (m_filteredTo.length > 0) { msg = getMessage(); @@ -275,7 +279,6 @@ public class Mail implements MessageType { // Close the transport agent and rethrow error for // detailed message. - transport.close(); throw new SendFailedException("send failed: ", mex); @@ -283,14 +286,13 @@ public class Mail implements MessageType { } // Write a copy of the message into the log file - if (MailConfig.getConfig().isDebug()) { if (msg != null) { try { ByteArrayOutputStream os = new ByteArrayOutputStream(); msg.writeTo(os); s_log.debug("message sent:\n" + os.toString() - + "\n-- EOT --"); + + "\n-- EOT --"); } catch (IOException ex) { s_log.error("unable to log message"); } @@ -299,15 +301,16 @@ public class Mail implements MessageType { } } else { s_log.info("message sent to <" + Arrays.asList(m_filteredTo) - + "> from <" + m_from + "> subject <" + m_subject + ">"); + + "> from <" + m_from + "> subject <" + m_subject + + ">"); s_log.info("messages filtered for <" + Arrays.asList(m_invalidTo) - + "> from <" + m_from + "> subject <" + m_subject + ">"); + + "> from <" + m_from + "> subject <" + m_subject + + ">"); } } /** - * Sets the email address that the message is being sent - * to. + * Sets the email address that the message is being sent to. * * @param to one or more addresses to send the message to */ @@ -317,8 +320,7 @@ public class Mail implements MessageType { } /** - * Sets the email address that the message is being sent - * from. + * Sets the email address that the message is being sent from. * * @param from the address the message is sent from */ @@ -365,7 +367,7 @@ public class Mail implements MessageType { /** * Adds a header (name, value) pair. * - * @param name the header element name + * @param name the header element name * @param value the header element value */ public void addHeader(String name, String value) { @@ -378,6 +380,7 @@ public class Mail implements MessageType { /** * Sets the email address that is being carbon-copied. + * * @param cc the email address for a carbon copy */ public void setCc(String cc) { @@ -386,6 +389,7 @@ public class Mail implements MessageType { /** * Sets the email address that is being blind carbon-copied. + * * @param bcc the email address for a blind carbon copy */ public void setBcc(String bcc) { @@ -394,6 +398,7 @@ public class Mail implements MessageType { /** * Sets the body of the email to a simple plain text message. + * * @param body the body of the message in plain text */ public void setBody(String body) { @@ -401,11 +406,11 @@ public class Mail implements MessageType { } /** - * Sets the body of the email to an HTML encoded message with a - * plain text alternative. + * Sets the body of the email to an HTML encoded message with a plain text + * alternative. * * @param body the body of the message in HTML - * @param alt the alternate message body in plain text + * @param alt the alternate message body in plain text */ public void setBody(String body, String alt) { m_body = body; @@ -423,8 +428,8 @@ public class Mail implements MessageType { } /** - * Returns the character encoding that is being used. The default - * is "us-ascii". + * Returns the character encoding that is being used. The default is + * "us-ascii". * * @return the string value of the character encoding being used */ @@ -433,14 +438,14 @@ public class Mail implements MessageType { } /** - * Adds an attachment to a message. This method is private but - * is invoked by all of the other attach methods once they've - * constructed an appropraite MimeBodyPart to attach. + * Adds an attachment to a message. This method is private but is invoked by + * all of the other attach methods once they've constructed an appropraite + * MimeBodyPart to attach. * * @param part the message part to attach */ private void attach(MimeBodyPart part) - throws MessagingException { + throws MessagingException { if (m_attachments == null) { m_attachments = new MimeMultipart(); } @@ -448,27 +453,26 @@ public class Mail implements MessageType { } /** - * Adds an attachment with a specified name and description to a - * message by fetching its content from a URL. Sets the - * disposition to ATTACHMENT. + * Adds an attachment with a specified name and description to a message by + * fetching its content from a URL. Sets the disposition to ATTACHMENT. * - * @param url the URL to retreieve the content from - * @param name the name of the attachment + * @param url the URL to retreieve the content from + * @param name the name of the attachment * @param description a description of the attachment */ public void attach(URL url, String name, String description) - throws MessagingException { + throws MessagingException { attach(url, name, description, Mail.ATTACHMENT); } /** - * Adds an attachment with a specified name, description and - * disposition to a message by fetching its content from a URL. + * Adds an attachment with a specified name, description and disposition to + * a message by fetching its content from a URL. * - * @param url the URL to retreieve the content from - * @param name the name of the attachment + * @param url the URL to retreieve the content from + * @param name the name of the attachment * @param description a description of the attachment * @param disposition Mail.ATTACHMENT or Mail.INLINE */ @@ -476,7 +480,7 @@ public class Mail implements MessageType { String name, String description, String disposition) - throws MessagingException { + throws MessagingException { MimeBodyPart part = new MimeBodyPart(); attach(part); @@ -489,28 +493,27 @@ public class Mail implements MessageType { } /** - * Adds an attachment with a specified name and description to a - * message by fetching its content from a local file. Sets the - * disposition to ATTACHMENT. + * Adds an attachment with a specified name and description to a message by + * fetching its content from a local file. Sets the disposition to + * ATTACHMENT. * - * @param path the file path to retreieve the content from - * @param name the name of the attachment + * @param path the file path to retreieve the content from + * @param name the name of the attachment * @param description a description of the attachment */ public void attach(File path, String name, String description) - throws MessagingException { + throws MessagingException { attach(path, name, description, ATTACHMENT); } /** - * Adds an attachment with a specified name, description and - * disposition to a message by fetching its content from a - * local file. + * Adds an attachment with a specified name, description and disposition to + * a message by fetching its content from a local file. * - * @param path the file path to retreieve the content from - * @param name the name of the attachment + * @param path the file path to retreieve the content from + * @param name the name of the attachment * @param description a description of the attachment * @param disposition Mail.ATTACHMENT or Mail.INLINE */ @@ -518,7 +521,7 @@ public class Mail implements MessageType { String name, String description, String disposition) - throws MessagingException { + throws MessagingException { MimeBodyPart part = new MimeBodyPart(); attach(part); @@ -531,9 +534,8 @@ public class Mail implements MessageType { } /** - * Attaches a byte array to a message. Sets the MIME type and - * name of the attachment, and initializes its disposition to - * ATTACHMENT. + * Attaches a byte array to a message. Sets the MIME type and name of the + * attachment, and initializes its disposition to ATTACHMENT. * * @param data the content of the attachment * @param type the MIME type of the attachment @@ -542,19 +544,20 @@ public class Mail implements MessageType { public void attach(byte[] data, String type, String name) - throws MessagingException { + throws MessagingException { attach(data, type, name, null, ATTACHMENT); } /** - * Attaches a byte array to a message. Sets the MIME type, name, - * description and disposition of the attachment. + * Attaches a byte array to a message. Sets the MIME type, name, description + * and disposition of the attachment. * - * @param data the content of the attachment - * @param type the MIME type of the attachment - * @param name the name of the attachment + * @param data the content of the attachment + * @param type the MIME type of the attachment + * @param name the name of the attachment * @param description a description of the attachment * @param disposition Mail.ATTACHMENT or Mail.INLINE + * * @throws javax.mail.MessagingException */ public void attach(byte[] data, @@ -562,14 +565,14 @@ public class Mail implements MessageType { String name, String description, String disposition) - throws MessagingException { + throws MessagingException { ByteArrayDataSource ds = new ByteArrayDataSource(data, type, name); attach(ds, description, disposition); } /** - * Attaches a String to a message. Sets the MIME type and name of - * the attachment, and initializes the disposition to ATTACHMENT. + * Attaches a String to a message. Sets the MIME type and name of the + * attachment, and initializes the disposition to ATTACHMENT. * * @param data the content of the attachment * @param type the MIME type of the attachment @@ -578,17 +581,17 @@ public class Mail implements MessageType { public void attach(String data, String type, String name) - throws MessagingException { + throws MessagingException { attach(data, type, name, null, ATTACHMENT); } /** - * Attaches a String to a message. Sets the MIME type, name, - * description and disposition of the attachment. + * Attaches a String to a message. Sets the MIME type, name, description and + * disposition of the attachment. * - * @param data the content of the attachment - * @param type the MIME type of the attachment - * @param name the name of the attachment + * @param data the content of the attachment + * @param type the MIME type of the attachment + * @param name the name of the attachment * @param description a description of the attachment * @param disposition Mail.ATTACHMENT or Mail.INLINE */ @@ -597,35 +600,34 @@ public class Mail implements MessageType { String name, String description, String disposition) - throws MessagingException { + throws MessagingException { ByteArrayDataSource ds = new ByteArrayDataSource(data, type, name); attach(ds, description, disposition); } /** - * Attaches the content from a ByteArrayInputStream to a message. - * Sets the MIME type and name of the attachment, and initializes - * the disposition to ATTACHMENT. + * Attaches the content from a ByteArrayInputStream to a message. Sets the + * MIME type and name of the attachment, and initializes the disposition to + * ATTACHMENT. * - * @param is the input stream to read from. + * @param is the input stream to read from. * @param type the MIME type of the attachment * @param name the name of the attachment */ public void attach(ByteArrayInputStream is, String type, String name) - throws MessagingException { + throws MessagingException { attach(is, type, name, null, ATTACHMENT); } /** - * Attaches the content from a ByteArrayInputStream to a message. - * Sets the MIME type, name, description and disposition of the - * attachment. + * Attaches the content from a ByteArrayInputStream to a message. Sets the + * MIME type, name, description and disposition of the attachment. * - * @param is the input stream to read from. - * @param type the MIME type of the attachment - * @param name the name of the attachment + * @param is the input stream to read from. + * @param type the MIME type of the attachment + * @param name the name of the attachment * @param description a description of the attachment * @param disposition Mail.ATTACHMENT or Mail.INLINE */ @@ -634,25 +636,25 @@ public class Mail implements MessageType { String name, String description, String disposition) - throws MessagingException { + throws MessagingException { ByteArrayDataSource ds = new ByteArrayDataSource(is, type, name); attach(ds, description, disposition); } /** - * Attaches the content from a ByteArrayDataSource to a - * message. This is used internally by various other methods that - * take higher-level object types as input. The MIME type and - * name are determined directly from the dataSource. + * Attaches the content from a ByteArrayDataSource to a message. This is + * used internally by various other methods that take higher-level object + * types as input. The MIME type and name are determined directly from the + * dataSource. * - * @param dataSource the data source to read from - * @param description a description of the attachment + * @param dataSource the data source to read from + * @param description a description of the attachment * @param disposition Mail.ATTACHMENT or Mail.INLINE */ protected void attach(ByteArrayDataSource dataSource, String description, String disposition) - throws MessagingException { + throws MessagingException { MimeBodyPart part = new MimeBodyPart(); attach(part); @@ -665,29 +667,29 @@ public class Mail implements MessageType { } /** - * Attaches content to a message by supplying a DataHandler. All - * relevant parameters (MIME type, name, ...) are determined - * directly from the DataHandler. + * Attaches content to a message by supplying a DataHandler. All relevant + * parameters (MIME type, name, ...) are determined directly from the + * DataHandler. * * @param dh a DataHandler for some piece of content. */ public void attach(DataHandler dh) - throws MessagingException { + throws MessagingException { attach(dh, null, ATTACHMENT); } /** - * Attaches content to a message by supplying a DataHandler. Sets - * the description and disposition of the content. + * Attaches content to a message by supplying a DataHandler. Sets the + * description and disposition of the content. * - * @param dh the data source to read from + * @param dh the data source to read from * @param description a description of the attachment * @param disposition Mail.ATTACHMENT or Mail.INLINE */ public void attach(DataHandler dh, String description, String disposition) - throws MessagingException { + throws MessagingException { MimeBodyPart part = new MimeBodyPart(); attach(part); @@ -698,10 +700,9 @@ public class Mail implements MessageType { } /** - * Utility function that returns an appropriate Session object for - * sending mail. This uses the default properties from the Mail - * initializer and any of properties that can be overridden at - * the package level. + * Utility function that returns an appropriate Session object for sending + * mail. This uses the default properties from the Mail initializer and any + * of properties that can be overridden at the package level. */ static synchronized Session getSession() { @@ -721,20 +722,21 @@ public class Mail implements MessageType { // Set up the session s_session = Session.getInstance(props, null); - s_session.setDebug(MailConfig.getConfig().isDebug()); +// s_session.setDebug(MailConfig.getConfig().isDebug()); + s_session.setDebug(true); } return s_session; } /** - * Utility function that returns the message part of the mail. - * Useful if you want to build a separate Transport process (for - * example, to queue a number of messages to send all at once rather - * than invoke the Mail.send() method for each instance.) + * Utility function that returns the message part of the mail. Useful if you + * want to build a separate Transport process (for example, to queue a + * number of messages to send all at once rather than invoke the Mail.send() + * method for each instance.) */ private Message getMessage() - throws MessagingException { + throws MessagingException { // Create the message MimeMessage msg = new MimeMessage(getSession()); @@ -789,14 +791,13 @@ public class Mail implements MessageType { } // Return the Message object with it's content ready to go. - return prepareMessageContent(msg); } /** - * Sets the host and port to connect to when sending - * mail. Package-level access (should only be used for testing). + * Sets the host and port to connect to when sending mail. Package-level + * access (should only be used for testing). * * @param host the SMTP host to connect to * @param port the port number on that host @@ -811,6 +812,7 @@ public class Mail implements MessageType { /** * Returns the SMTP mail host for debugging and account information. + * * @return the SMTP mail host for debugging and account information. */ public synchronized static String getSmtpServer() { @@ -818,13 +820,13 @@ public class Mail implements MessageType { } /** - * Writes the content of the message to the given output stream. - * Useful for debugging. + * Writes the content of the message to the given output stream. Useful for + * debugging. * * @param os the output stream to write the message to */ public void writeTo(OutputStream os) - throws MessagingException { + throws MessagingException { try { getMessage().writeTo(os); } catch (IOException ex) { @@ -946,7 +948,7 @@ public class Mail implements MessageType { * Utility function to prepare the content of the message. */ private Message prepareMessageContent(MimeMessage msg) - throws MessagingException { + throws MessagingException { if (m_alternate == null && m_attachments == null) { // We have a plain-text message with no attachments. Use @@ -959,24 +961,20 @@ public class Mail implements MessageType { // For anything else the message will be a MIME multipart, // with a subtype of of either "mixed" or "alternative" // depending on whether we have attachments. - String subtype = (m_attachments == null) ? ALTERNATIVE : MIXED; // Create a MIME multipart for the content. - MimeMultipart mp = new MimeMultipart(subtype); msg.setContent(mp); // Next we need to look at whether the message part of the // content is going to be text/plain or text/html. - MimeBodyPart part = new MimeBodyPart(); if (m_alternate == null) { // No alternate, so it must be text/plain with // attachments. - part.setText(m_body, m_encoding); part.setHeader(CONTENT_TYPE, MessageType.TEXT_PLAIN); mp.addBodyPart(part); @@ -987,12 +985,10 @@ public class Mail implements MessageType { // the first part and the alternate as the second. // The overall MIME subtype is probably ALTERNATE // (depending on whether we have attachments). - part.setText(m_body, m_encoding); part.setHeader(CONTENT_TYPE, MessageType.TEXT_HTML); mp.addBodyPart(part); - part = new MimeBodyPart(); part.setText(m_alternate, m_encoding); part.setHeader(CONTENT_TYPE, MessageType.TEXT_PLAIN); @@ -1003,11 +999,9 @@ public class Mail implements MessageType { // Do we have attachments? If so then the MIME subtype // must be MIXED and and the attachments need to be // transferred to the Message. - if (m_attachments != null) { // Add attachments to the Message content. - for (int i = 0; i < m_attachments.getCount(); i++) { mp.addBodyPart(m_attachments.getBodyPart(i)); } @@ -1016,14 +1010,13 @@ public class Mail implements MessageType { // Save changes to the message. This will update the MIME // headers so the message is ready to send. - msg.saveChanges(); return msg; } /** - * + * */ private InternetAddress[] filterRecipients() { ArrayList filtered = new ArrayList(); @@ -1042,13 +1035,16 @@ public class Mail implements MessageType { } else { invalid.add(m_to[i]); s_log.debug("filtering message to non-existent email address " - + m_to[i]); + + m_to[i]); } } - m_filteredTo = (InternetAddress[]) filtered.toArray(new InternetAddress[filtered. - size()]); - m_invalidTo = (InternetAddress[]) invalid.toArray(new InternetAddress[invalid. - size()]); + m_filteredTo = (InternetAddress[]) filtered.toArray( + new InternetAddress[filtered. + size()]); + m_invalidTo = (InternetAddress[]) invalid.toArray( + new InternetAddress[invalid. + size()]); return m_filteredTo; } + } diff --git a/ccm-core/src/main/java/com/arsdigita/mail/MailConfig.java b/ccm-core/src/main/java/com/arsdigita/mail/MailConfig.java index 7cfa5a709..17e89a617 100755 --- a/ccm-core/src/main/java/com/arsdigita/mail/MailConfig.java +++ b/ccm-core/src/main/java/com/arsdigita/mail/MailConfig.java @@ -72,15 +72,26 @@ public final class MailConfig { if (javaMailPropertiesFile == null || javaMailPropertiesFile.isEmpty()) { - properties.put("mail.transport.protocol", "smtp"); - properties.put("mail.smtp.host", "localhost"); + if (System.getProperty("ccm.mail.config") == null) { + properties.put("mail.transport.protocol", "smtp"); + properties.put("mail.smtp.host", "localhost"); + } else { + try { + properties.load(new URL(System + .getProperty("ccm.mail.config")).openStream()); + } catch (IOException ex) { + throw new UncheckedWrapperException(String.format( + "Unable to retrieve properties for JavaMail from \"%s\".", + System.getProperty("ccm.mail.config")), ex); + } + } } else { try { properties.load(new URL(javaMailPropertiesFile).openStream()); } catch (IOException ex) { throw new UncheckedWrapperException(String.format( "Unable to retrieve properties for JavaMail from \"%s\".", - javaMailPropertiesFile)); + javaMailPropertiesFile), ex); } } diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserAdmin.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserAdmin.java index cc8733144..b0fd71caf 100644 --- a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserAdmin.java +++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserAdmin.java @@ -23,7 +23,6 @@ import com.arsdigita.bebop.BoxPanel; import com.arsdigita.bebop.Component; import com.arsdigita.bebop.ControlLink; import com.arsdigita.bebop.Form; -import com.arsdigita.bebop.FormProcessException; import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Page; import com.arsdigita.bebop.PageState; @@ -32,26 +31,32 @@ import com.arsdigita.bebop.PropertySheet; import com.arsdigita.bebop.SaveCancelSection; import com.arsdigita.bebop.Table; import com.arsdigita.bebop.Text; -import com.arsdigita.bebop.event.FormProcessListener; -import com.arsdigita.bebop.event.FormSectionEvent; import com.arsdigita.bebop.event.TableActionEvent; import com.arsdigita.bebop.event.TableActionListener; import com.arsdigita.bebop.form.CheckboxGroup; import com.arsdigita.bebop.form.Option; import com.arsdigita.bebop.form.Submit; import com.arsdigita.bebop.form.TextField; -import com.arsdigita.bebop.parameters.LongParameter; +import com.arsdigita.bebop.parameters.NotEmptyValidationListener; import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.bebop.table.TableCellRenderer; import com.arsdigita.bebop.table.TableColumn; import com.arsdigita.bebop.table.TableColumnModel; import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.mail.Mail; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.core.EmailAddress; import org.libreccm.security.User; +import org.libreccm.security.UserManager; import org.libreccm.security.UserRepository; +import java.util.logging.Level; + +import javax.mail.MessagingException; + import static com.arsdigita.ui.admin.AdminUiConstants.*; /** @@ -59,8 +64,10 @@ import static com.arsdigita.ui.admin.AdminUiConstants.*; * @author Jens Pelzetter */ public class UserAdmin extends BoxPanel { - - private final LongParameter userIdParameter; + + private static final Logger LOGGER = LogManager.getLogger(UserAdmin.class); + + private final StringParameter userIdParameter; private final StringParameter emailParameter; private final ParameterSingleSelectionModel selectedUserId; private final ParameterSingleSelectionModel selectedEmailAddress; @@ -73,15 +80,15 @@ public class UserAdmin extends BoxPanel { // private final UserDetails userDetails; private final BoxPanel userDetails; private final Form emailForm; - + public UserAdmin() { super(); - + setIdAttr("userAdmin"); - + usersTablePanel = new BoxPanel(); usersTablePanel.setIdAttr("usersTablePanel"); - + final Form filterForm = new Form("usersTableFilterForm"); usersTableFilter = new TextField("usersTableFilter"); usersTableFilter.setLabel(new GlobalizedMessage( @@ -97,18 +104,18 @@ public class UserAdmin extends BoxPanel { }); filterForm.add(clearLink); usersTablePanel.add(filterForm); - - userIdParameter = new LongParameter("selected_user_id"); + + userIdParameter = new StringParameter("selected_user_id"); selectedUserId = new ParameterSingleSelectionModel<>(userIdParameter); //selectedUserId = new ParameterSingleSelectionModel<>(USER_ID_PARAM); emailParameter = new StringParameter("selected_email_address"); selectedEmailAddress = new ParameterSingleSelectionModel<>( emailParameter); - + usersTable = new UsersTable(this, usersTableFilter, selectedUserId); usersTablePanel.add(usersTable); - + add(usersTablePanel); // final Text text = new Text(); @@ -124,19 +131,19 @@ public class UserAdmin extends BoxPanel { // add(new UserDetails(this, selectedUserId)); userDetails = new BoxPanel(); userDetails.setIdAttr("userDetails"); - + backToUsersTable = new ActionLink(new GlobalizedMessage( "ui.admin.user_details.back", ADMIN_BUNDLE)); backToUsersTable.setIdAttr("userDetailsBackLink"); backToUsersTable.addActionListener( e -> closeUserDetails(e.getPageState())); userDetails.add(backToUsersTable); - + userProperties = new PropertySheet(new UserPropertySheetModelBuilder( this, selectedUserId)); userProperties.setIdAttr("userProperties"); userDetails.add(userProperties); - + actionLinks = new BoxPanel(BoxPanel.HORIZONTAL); actionLinks.setIdAttr("userDetailsActionLinks"); final ActionLink editUserDetailsLink = new ActionLink( @@ -146,7 +153,7 @@ public class UserAdmin extends BoxPanel { }); actionLinks.add(editUserDetailsLink); actionLinks.add(new Text(" | ")); - + final ActionLink setPasswordLink = new ActionLink( new GlobalizedMessage("ui.admin.user_details.set_password", ADMIN_BUNDLE)); @@ -155,16 +162,33 @@ public class UserAdmin extends BoxPanel { }); actionLinks.add(setPasswordLink); actionLinks.add(new Text(" | ")); - + final ActionLink generatePasswordLink = new ActionLink( new GlobalizedMessage("ui.admin.user_details.generate_password", ADMIN_BUNDLE)); + generatePasswordLink.setConfirmation(new GlobalizedMessage( + "ui.admin.user_details.generate_password.confirm", + ADMIN_BUNDLE)); generatePasswordLink.addActionListener(e -> { - //ToDo + final UserRepository userRepository = CdiUtil.createCdiUtil().findBean(UserRepository.class); + final User user = userRepository.findById(Long.parseLong( + selectedUserId.getSelectedKey(e.getPageState()))); + + final Mail mail = new Mail( + user.getPrimaryEmailAddress().getAddress(), + "libreccm.example", + "New password has been generated."); + mail.setBody("Das eine Test-Email"); + + try { + mail.send(); + } catch (MessagingException ex) { + LOGGER.error("Failed to send email to user.", ex); + } }); actionLinks.add(generatePasswordLink); userDetails.add(actionLinks); - + final Table primaryEmailTable = new Table(); primaryEmailTable.setModelBuilder( new UserPrimaryEmailTableModelBuilder(selectedUserId)); @@ -193,7 +217,7 @@ public class UserAdmin extends BoxPanel { primaryEmailTableColModel.get( UserPrimaryEmailTableModel.COL_ACTION).setCellRenderer( new TableCellRenderer() { - + @Override public Component getComponent(final Table table, final PageState state, @@ -204,27 +228,27 @@ public class UserAdmin extends BoxPanel { final int column) { return new ControlLink((Label) value); } - + }); - + primaryEmailTable.addTableActionListener(new TableActionListener() { - + @Override public void cellSelected(final TableActionEvent event) { final String key = (String) event.getRowKey(); selectedEmailAddress.setSelectedKey(event.getPageState(), key); showEmailForm(event.getPageState()); } - + @Override public void headSelected(final TableActionEvent event) { //Nothing } - + }); - + userDetails.add(primaryEmailTable); - + final Table emailTable = new Table(); emailTable.setModelBuilder( new UserEmailTableModelBuilder(selectedUserId)); @@ -257,7 +281,7 @@ public class UserAdmin extends BoxPanel { ADMIN_BUNDLE)))); emailTableColumnModel.get(UserEmailTableModel.COL_EDIT).setCellRenderer( new TableCellRenderer() { - + @Override public Component getComponent(final Table table, final PageState state, @@ -266,14 +290,14 @@ public class UserAdmin extends BoxPanel { final Object key, final int row, final int column) { - return new ControlLink((Label) value); + return new ControlLink((Component) value); } - + }); emailTableColumnModel.get(UserEmailTableModel.COL_DELETE) .setCellRenderer( new TableCellRenderer() { - + @Override public Component getComponent(final Table table, final PageState state, @@ -282,35 +306,69 @@ public class UserAdmin extends BoxPanel { final Object key, final int row, final int column) { - return new ControlLink((Label) value); + final ControlLink link = new ControlLink((Component) value); + if (column == UserEmailTableModel.COL_DELETE) { + link.setConfirmation(new GlobalizedMessage( + "ui.admin.user.email_addresses.delete.confirm", + ADMIN_BUNDLE)); + } + return link; } - + }); emailTable.addTableActionListener(new TableActionListener() { - + @Override public void cellSelected(final TableActionEvent event) { - //ToDo + final PageState state = event.getPageState(); + + final String key = (String) event.getRowKey(); + + switch (event.getColumn()) { + case UserEmailTableModel.COL_EDIT: + selectedEmailAddress.setSelectedKey(state, key); + showEmailForm(state); + break; + case UserEmailTableModel.COL_DELETE: + final String userIdStr = selectedUserId.getSelectedKey( + state); + final UserRepository userRepository = CdiUtil + .createCdiUtil().findBean(UserRepository.class); + final User user = userRepository.findById(Long + .parseLong(userIdStr)); + EmailAddress email = null; + for (EmailAddress current : user.getEmailAddresses()) { + if (current.getAddress().equals(key)) { + email = current; + break; + } + } + + if (email != null) { + user.removeEmailAddress(email); + userRepository.save(user); + } + } } - + @Override public void headSelected(final TableActionEvent event) { //Nothing } - + }); emailTable.setEmptyView(new Label(new GlobalizedMessage( "ui.admin.user.email_addresses.none", ADMIN_BUNDLE))); - + userDetails.add(emailTable); - + final ActionLink addEmailLink = new ActionLink(new GlobalizedMessage( "ui.admin.user.email_addresses.add", ADMIN_BUNDLE)); addEmailLink.addActionListener(e -> { - //ToDo + showEmailForm(e.getPageState()); }); userDetails.add(addEmailLink); - + emailForm = new Form("email_form"); // emailForm.add(new Label(new GlobalizedMessage( // "ui.admin.user.email_form.address", @@ -318,6 +376,10 @@ public class UserAdmin extends BoxPanel { final TextField emailFormAddress = new TextField("email_form_address"); emailFormAddress.setLabel(new GlobalizedMessage( "ui.admin.user.email_form.address", ADMIN_BUNDLE)); + emailFormAddress.addValidationListener(new NotEmptyValidationListener( + new GlobalizedMessage("ui.admin.user.email_form.address.not_empty", + ADMIN_BUNDLE))); + emailForm.add(emailFormAddress); final CheckboxGroup emailFormVerified = new CheckboxGroup( "email_form_verified"); emailFormVerified.addOption( @@ -325,19 +387,21 @@ public class UserAdmin extends BoxPanel { new Label(new GlobalizedMessage( "ui.admin.user.email_form.verified", ADMIN_BUNDLE)))); + emailForm.add(emailFormVerified); final CheckboxGroup emailFormBouncing = new CheckboxGroup( - "email_form_verified"); + "email_form_bouncing"); emailFormBouncing.addOption( new Option("true", new Label(new GlobalizedMessage( "ui.admin.user.email_form.bouncing", ADMIN_BUNDLE)))); - + emailForm.add(emailFormBouncing); + emailForm.add(new SaveCancelSection()); - + emailForm.addInitListener(e -> { final PageState state = e.getPageState(); - + final String selected = selectedEmailAddress.getSelectedKey(state); final String userIdStr = selectedUserId.getSelectedKey(state); if (selected != null && !selected.isEmpty()) { @@ -356,7 +420,7 @@ public class UserAdmin extends BoxPanel { } } } - + if (email != null) { emailFormAddress.setValue(state, email.getAddress()); if (email.isVerified()) { @@ -370,63 +434,107 @@ public class UserAdmin extends BoxPanel { }); emailForm.addProcessListener(e -> { + final PageState state = e.getPageState(); + + final String selected = selectedEmailAddress.getSelectedKey(state); + final String userIdStr = selectedUserId.getSelectedKey(state); + + final UserRepository userRepository = CdiUtil.createCdiUtil() + .findBean(UserRepository.class); + final User user = userRepository.findById(Long.parseLong( + userIdStr)); + EmailAddress email = null; + if (selected == null) { + email = new EmailAddress(); + user.addEmailAddress(email); + } else if (user.getPrimaryEmailAddress().getAddress().equals( + selected)) { + email = user.getPrimaryEmailAddress(); + } else { + for (EmailAddress current : user.getEmailAddresses()) { + if (current.getAddress().equals(selected)) { + email = current; + break; + } + } + } + + if (email != null) { + email.setAddress((String) emailFormAddress.getValue(state)); + + final String[] verifiedValues = (String[]) emailFormVerified + .getValue(state); + if (verifiedValues != null && verifiedValues.length > 0) { + if ("true".equals(verifiedValues[0])) { + email.setVerified(true); + } else { + email.setVerified(false); + } + } else { + email.setVerified(false); + } + + final String[] bouncingValues = (String[]) emailFormBouncing + .getValue(state); + if (bouncingValues != null && bouncingValues.length > 0) { + if ("true".equals(bouncingValues[0])) { + email.setBouncing(true); + } else { + email.setBouncing(false); + } + } else { + email.setBouncing(false); + } + } + + userRepository.save(user); closeEmailForm(e.getPageState()); }); emailForm.addCancelListener(e -> closeEmailForm(e.getPageState())); - -// emailFormAddress.setLabel(new GlobalizedMessage( -// "ui.admin.user.email_form.verified", -// ADMIN_BUNDLE)); -// emailForm.add(new Label(new GlobalizedMessage( -// "ui.admin.user.email_form.verified", -// ADMIN_BUNDLE))); -// -// emailForm.add(new Label(new GlobalizedMessage( -// "ui.admin.user.email_form.bouncing", -// ADMIN_BUNDLE))); + add(emailForm); - + add(userDetails); - + } - + @Override public void register(final Page page) { super.register(page); - + page.addGlobalStateParam(userIdParameter); page.addGlobalStateParam(emailParameter); - + page.setVisibleDefault(usersTablePanel, true); page.setVisibleDefault(userDetails, false); page.setVisibleDefault(emailForm, false); } - + protected void showUserDetails(final PageState state) { usersTablePanel.setVisible(state, false); userDetails.setVisible(state, true); emailForm.setVisible(state, false); } - + protected void closeUserDetails(final PageState state) { selectedUserId.clearSelection(state); usersTablePanel.setVisible(state, true); userDetails.setVisible(state, false); emailForm.setVisible(state, false); } - + protected void showEmailForm(final PageState state) { usersTablePanel.setVisible(state, false); userDetails.setVisible(state, false); emailForm.setVisible(state, true); } - + protected void closeEmailForm(final PageState state) { selectedEmailAddress.clearSelection(state); usersTablePanel.setVisible(state, false); userDetails.setVisible(state, true); emailForm.setVisible(state, false); } - + } diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserEmailTableModel.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserEmailTableModel.java index 985a940fb..97519c9ee 100644 --- a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserEmailTableModel.java +++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/UserEmailTableModel.java @@ -42,7 +42,7 @@ public class UserEmailTableModel implements TableModel { protected static final int COL_DELETE = 4; private final List emailAddresses; - private int index; + private int index = -1; private boolean finished; public UserEmailTableModel(final User user) { @@ -56,12 +56,18 @@ public class UserEmailTableModel implements TableModel { @Override public boolean nextRow() { - if (index < emailAddresses.size()) { - index++; - return true; - } else { + if (emailAddresses == null || emailAddresses.isEmpty()) { return false; } +// if (index < emailAddresses.size()) { +// index++; +// return true; +// } else { +// return false; +// } + + index++; + return index < emailAddresses.size(); } @Override diff --git a/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java b/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java index b33859086..49ef0b30f 100644 --- a/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java +++ b/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java @@ -33,6 +33,7 @@ import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; +import javax.transaction.Transactional; /** * A base class providing common method needed by every repository. @@ -274,6 +275,7 @@ public abstract class AbstractEntityRepository { * * @param entity The entity to save. */ + @Transactional(Transactional.TxType.REQUIRED) public void save(final E entity) { if (isNew(entity)) { initNewEntity(entity); diff --git a/ccm-core/src/main/java/org/libreccm/security/User.java b/ccm-core/src/main/java/org/libreccm/security/User.java index 0e875d15f..bc1f12981 100644 --- a/ccm-core/src/main/java/org/libreccm/security/User.java +++ b/ccm-core/src/main/java/org/libreccm/security/User.java @@ -225,11 +225,11 @@ public class User extends Party implements Serializable { this.emailAddresses = emailAddresses; } - protected void addEmailAddress(final EmailAddress emailAddress) { + public void addEmailAddress(final EmailAddress emailAddress) { emailAddresses.add(emailAddress); } - protected void removeEmailAddress(final EmailAddress emailAddress) { + public void removeEmailAddress(final EmailAddress emailAddress) { emailAddresses.remove(emailAddress); } diff --git a/ccm-core/src/main/resources/com/arsdigita/bebop/BebopResources.properties b/ccm-core/src/main/resources/com/arsdigita/bebop/BebopResources.properties new file mode 100755 index 000000000..20e6540fc --- /dev/null +++ b/ccm-core/src/main/resources/com/arsdigita/bebop/BebopResources.properties @@ -0,0 +1,100 @@ +bebop.demo.demobebop_has_been_merged_with_bebopdemo=Demo-bebop has been merged with bebop-demo. +bebop.demo.go_there=Go there +bebop.demo.this_is_the_main_content_area=this is the main content area. +bebop.demo.four_score_and_seven_years_ago_blah_blah=four score and seven years ago... blah blah... +bebop.demo.tab_a=Tab A +bebop.demo.tab_b=Tab B +bebop.demo.this_outer_panel_runs_across=This outer panel runs across +bebop.demo.this_is_in_the_outer_panel_again=This is in the outer panel again +bebop.demo.this_inner_panel_runs_downwards=This inner panel runs downwards. +bebop.demo.its_axis_defaults_to_vertical=Its axis defaults to VERTICAL, +bebop.demo.centering_to_false=centering to false, +bebop.demo.border_to_0_false=border to 0 (false), +bebop.demo.and_its_width_is_unconstrained=and its width is unconstrained. +bebop.demo.hello_world_=Hello, World ! +bebop.demo.link_text=Link Text +bebop.demo.you_are_connecting_from=You are connecting from +bebop.demo.dont_care=don't care +bebop.demo.your_request_header_specifies=Your request header specifies +bebop.demo.this_should_be_full_width_aligned_right=This should be full width, aligned right +bebop.demo.this_should_be_full_width_and_centered=This should be full width and centered +bebop.demo.this_should_not_be_full_width=This should not be full width +bebop.demo.yet_another_single_column=yet another single column +bebop.demo.third_1_column_cell=Third 1 column cell +bebop.demo.lone_cell_makes_table_look_bad=lone cell makes table look bad +bebop.demo.centered_across_the_full_width=Centered across the full width +bebop.demo.only_one_column=only one column +bebop.demo.rightaligned_single_column=right-aligned single column +bebop.demo.full_width_and_aligned_right=full width and aligned right +bebop.demo.lonely_cell_on_last_row=lonely cell on last row +bebop.demo.this_is_the_blurb=this is the Blurb +bebop.demo.a_static_label=A static label +bebop.demo.this_should_be_full_width_too=This should be full width too +bebop.demo.header=Header +bebop.demo.left_component=Left Component +bebop.demo.right_component=Right Component +bebop.demo.ignored=Ignored +bebop.demo.this_pane_talks_about_monocotyledons=This pane talks about monocotyledons +bebop.demo.this_pane_talks_about_dicotyledons=This pane talks about dicotyledons +bebop.demo.street=Street +bebop.demo.country=Country +bebop.demo.subscribe_to_our_mailing_list=Subscribe to our mailing list +bebop.demo.name=Name: +bebop.demo.age=Age: +bebop.demo.email_required=Email (required): +bebop.demo.why_would_you_ever_want_to_subscribe_to_spam_=Why would you ever want to subscribe to spam ? +bebop.demo.customize_your_sandwich=Customize Your Sandwich +bebop.demo.protein=Protein: +bebop.demo.vitamins=Vitamins: +bebop.demo.sauce=Sauce: +bebop.demo.payment_method=Payment Method: +bebop.demo.now_with_100_more_tofu_=Now with 100% more tofu ! +bebop.demo.delivery=Delivery +bebop.demo.shipment_method=Shipment Method: +bebop.demo.purchase=Purchase +bebop.demo.animal_kingdom_little_lamb=Animal Kingdom: Little Lamb +bebop.demo.workflow.process_name=Process Name +bebop.demo.workflow.short_description=Short Description +bebop.demo.workflow.name=Name +bebop.demo.workflow.task=Task +bebop.demo.workflow.description=Description +bebop.demo.workflow.depends_on=Depends on +bebop.demo.workflow.h4emselect_process_to_view_detailsemh4=

Select Process to View Details

+bebop.demo.workflow.task_details=Task details +bebop.demo.workflow.default_assignee_group=Default assignee group +bebop.demo.workflow.dependencies=Dependencies +bebop.demo.workflow.add_dependency=Add dependency +bebop.demo.workflow.none=None +bebop.demo.workflow.h4workflow_templatesh4=

Workflow Templates

+bebop.demo.workflow.add_template=add template +bebop.page=Page: +bebop.previous=Previous +bebop.next=Next +bebop.please_select_choice_from_the_list_on_the_left=Please select choice from the list on the left +bebop.send_email_to_everybody=Send email to everybody +bebop.basic_item_metadata=Basic Item Metadata +bebop.title=Title: +bebop.click_here=click here +bebop.demo.foo_is_null=foo is null. +bebop.demo.this_link_showshides_the_blurb=This link shows/hides the Blurb +bebop.demo.no_action=no action +bebop.event.default_text=Default text +bebop.event.call_no=Call no. +bebop.first_name=First Name: +bebop.last_name=Last Name: +bebop.hello_world=Hello World +bebop.edit_the_foo_property=Edit the Foo property +bebop.table.=  +bebop.the_table_is_empty=The table is empty +bebop.util.some_text=Some Text +bebop.subject=Subject +bebop.body=Body +bebop.are_you_sure=Are you sure? +bebop.the_model_is_empty=The Model is Empty +bebop.save=Save +bebop.cancel=Cancel +bebop.cancel.msg=Submission Cancelled +bebop.parameter.unexpected_value_type=Unexpected value type: {0} +bebop.date.year.hint=Year +bebop.date.year.label=Year +bebop.hint.no_entry_yet=No information available yet. diff --git a/ccm-core/src/main/resources/com/arsdigita/bebop/BebopResources_de.properties b/ccm-core/src/main/resources/com/arsdigita/bebop/BebopResources_de.properties new file mode 100644 index 000000000..0af5a6ece --- /dev/null +++ b/ccm-core/src/main/resources/com/arsdigita/bebop/BebopResources_de.properties @@ -0,0 +1,100 @@ +bebop.demo.demobebop_has_been_merged_with_bebopdemo=Demo-bebop has been merged with bebop-demo. +bebop.demo.go_there=Go there +bebop.demo.this_is_the_main_content_area=this is the main content area. +bebop.demo.four_score_and_seven_years_ago_blah_blah=four score and seven years ago... blah blah... +bebop.demo.tab_a=Tab A +bebop.demo.tab_b=Tab B +bebop.demo.this_outer_panel_runs_across=This outer panel runs across +bebop.demo.this_is_in_the_outer_panel_again=This is in the outer panel again +bebop.demo.this_inner_panel_runs_downwards=This inner panel runs downwards. +bebop.demo.its_axis_defaults_to_vertical=Its axis defaults to VERTICAL, +bebop.demo.centering_to_false=centering to false, +bebop.demo.border_to_0_false=border to 0 (false), +bebop.demo.and_its_width_is_unconstrained=and its width is unconstrained. +bebop.demo.hello_world_=Hello, World ! +bebop.demo.link_text=Link Text +bebop.demo.you_are_connecting_from=You are connecting from +bebop.demo.dont_care=don't care +bebop.demo.your_request_header_specifies=Your request header specifies +bebop.demo.this_should_be_full_width_aligned_right=This should be full width, aligned right +bebop.demo.this_should_be_full_width_and_centered=This should be full width and centered +bebop.demo.this_should_not_be_full_width=This should not be full width +bebop.demo.yet_another_single_column=yet another single column +bebop.demo.third_1_column_cell=Third 1 column cell +bebop.demo.lone_cell_makes_table_look_bad=lone cell makes table look bad +bebop.demo.centered_across_the_full_width=Centered across the full width +bebop.demo.only_one_column=only one column +bebop.demo.rightaligned_single_column=right-aligned single column +bebop.demo.full_width_and_aligned_right=full width and aligned right +bebop.demo.lonely_cell_on_last_row=lonely cell on last row +bebop.demo.this_is_the_blurb=this is the Blurb +bebop.demo.a_static_label=A static label +bebop.demo.this_should_be_full_width_too=This should be full width too +bebop.demo.header=Header +bebop.demo.left_component=Left Component +bebop.demo.right_component=Right Component +bebop.demo.ignored=Ignored +bebop.demo.this_pane_talks_about_monocotyledons=This pane talks about monocotyledons +bebop.demo.this_pane_talks_about_dicotyledons=This pane talks about dicotyledons +bebop.demo.street=Street +bebop.demo.country=Country +bebop.demo.subscribe_to_our_mailing_list=Subscribe to our mailing list +bebop.demo.name=Name: +bebop.demo.age=Age: +bebop.demo.email_required=Email (required): +bebop.demo.why_would_you_ever_want_to_subscribe_to_spam_=Why would you ever want to subscribe to spam ? +bebop.demo.customize_your_sandwich=Customize Your Sandwich +bebop.demo.protein=Protein: +bebop.demo.vitamins=Vitamins: +bebop.demo.sauce=Sauce: +bebop.demo.payment_method=Payment Method: +bebop.demo.now_with_100_more_tofu_=Now with 100% more tofu ! +bebop.demo.delivery=Delivery +bebop.demo.shipment_method=Shipment Method: +bebop.demo.purchase=Purchase +bebop.demo.animal_kingdom_little_lamb=Animal Kingdom: Little Lamb +bebop.demo.workflow.process_name=Process Name +bebop.demo.workflow.short_description=Short Description +bebop.demo.workflow.name=Name +bebop.demo.workflow.task=Task +bebop.demo.workflow.description=Description +bebop.demo.workflow.depends_on=Depends on +bebop.demo.workflow.h4emselect_process_to_view_detailsemh4=

Select Process to View Details

+bebop.demo.workflow.task_details=Task details +bebop.demo.workflow.default_assignee_group=Default assignee group +bebop.demo.workflow.dependencies=Dependencies +bebop.demo.workflow.add_dependency=Add dependency +bebop.demo.workflow.none=None +bebop.demo.workflow.h4workflow_templatesh4=

Workflow Templates

+bebop.demo.workflow.add_template=add template +bebop.page=Seite: +bebop.previous=Zur\u00fcck +bebop.next=Weiter +bebop.please_select_choice_from_the_list_on_the_left=Bitte eine Auswahl aus der Liste links treffen +bebop.send_email_to_everybody=Sende E-Mail an alle +bebop.basic_item_metadata=Basis Metadaten +bebop.title=Titel: +bebop.click_here=Hier klicken +bebop.demo.foo_is_null=foo is null. +bebop.demo.this_link_showshides_the_blurb=This link shows/hides the Blurb +bebop.demo.no_action=no action +bebop.event.default_text=Default Text +bebop.event.call_no=Call no. +bebop.first_name=Vorname: +bebop.last_name=Nachname: +bebop.hello_world=Hallo Welt +bebop.edit_the_foo_property=Edit the Foo property +bebop.table.=  +bebop.the_table_is_empty=The table is empty +bebop.util.some_text=Beliebiger Text +bebop.subject=Betreff +bebop.body=Body +bebop.are_you_sure=Sind Sie sicher? +bebop.the_model_is_empty=The Model is Empty +bebop.save=Speichern +bebop.cancel=Abbrechen +bebop.cancel.msg=Bearbeitung abgebrochen +bebop.parameter.unexpected_value_type=Unerwarteter Typ des Wertes: {0} +bebop.date.year.hint=Jahr +bebop.date.year.label=Jahr +bebop.hint.no_entry_yet=Gegenw\u00e4rtig noch keine Information verf\u00fcgbar. diff --git a/ccm-core/src/main/resources/com/arsdigita/bebop/BebopResources_fr.properties b/ccm-core/src/main/resources/com/arsdigita/bebop/BebopResources_fr.properties new file mode 100755 index 000000000..f68772cca --- /dev/null +++ b/ccm-core/src/main/resources/com/arsdigita/bebop/BebopResources_fr.properties @@ -0,0 +1,100 @@ +bebop.demo.demobebop_has_been_merged_with_bebopdemo=TRANSLATE THIS: Demo-bebop has been merged with bebop-demo. (bebop.demo.demobebop_has_been_merged_with_bebopdemo) +bebop.demo.go_there=TRANSLATE THIS: Go there (bebop.demo.go_there) +bebop.demo.this_is_the_main_content_area=TRANSLATE THIS: this is the main content area. (bebop.demo.this_is_the_main_content_area) +bebop.demo.four_score_and_seven_years_ago_blah_blah=TRANSLATE THIS: four score and seven years ago... blah blah... (bebop.demo.four_score_and_seven_years_ago_blah_blah) +bebop.demo.tab_a=TRANSLATE THIS: Tab A (bebop.demo.tab_a) +bebop.demo.tab_b=TRANSLATE THIS: Tab B (bebop.demo.tab_b) +bebop.demo.this_outer_panel_runs_across=TRANSLATE THIS: This outer panel runs across (bebop.demo.this_outer_panel_runs_across) +bebop.demo.this_is_in_the_outer_panel_again=TRANSLATE THIS: This is in the outer panel again (bebop.demo.this_is_in_the_outer_panel_again) +bebop.demo.this_inner_panel_runs_downwards=TRANSLATE THIS: This inner panel runs downwards. (bebop.demo.this_inner_panel_runs_downwards) +bebop.demo.its_axis_defaults_to_vertical=TRANSLATE THIS: Its axis defaults to VERTICAL, (bebop.demo.its_axis_defaults_to_vertical) +bebop.demo.centering_to_false=TRANSLATE THIS: centering to false, (bebop.demo.centering_to_false) +bebop.demo.border_to_0_false=TRANSLATE THIS: border to 0 (false), (bebop.demo.border_to_0_false) +bebop.demo.and_its_width_is_unconstrained=TRANSLATE THIS: and its width is unconstrained. (bebop.demo.and_its_width_is_unconstrained) +bebop.demo.hello_world_=TRANSLATE THIS: Hello, World ! (bebop.demo.hello_world_) +bebop.demo.link_text=TRANSLATE THIS: Link Text (bebop.demo.link_text) +bebop.demo.you_are_connecting_from=TRANSLATE THIS: You are connecting from (bebop.demo.you_are_connecting_from) +bebop.demo.dont_care=TRANSLATE THIS: don't care (bebop.demo.dont_care) +bebop.demo.your_request_header_specifies=TRANSLATE THIS: Your request header specifies (bebop.demo.your_request_header_specifies) +bebop.demo.this_should_be_full_width_aligned_right=TRANSLATE THIS: This should be full width, aligned right (bebop.demo.this_should_be_full_width_aligned_right) +bebop.demo.this_should_be_full_width_and_centered=TRANSLATE THIS: This should be full width and centered (bebop.demo.this_should_be_full_width_and_centered) +bebop.demo.this_should_not_be_full_width=TRANSLATE THIS: This should not be full width (bebop.demo.this_should_not_be_full_width) +bebop.demo.yet_another_single_column=TRANSLATE THIS: yet another single column (bebop.demo.yet_another_single_column) +bebop.demo.third_1_column_cell=TRANSLATE THIS: Third 1 column cell (bebop.demo.third_1_column_cell) +bebop.demo.lone_cell_makes_table_look_bad=TRANSLATE THIS: lone cell makes table look bad (bebop.demo.lone_cell_makes_table_look_bad) +bebop.demo.centered_across_the_full_width=TRANSLATE THIS: Centered across the full width (bebop.demo.centered_across_the_full_width) +bebop.demo.only_one_column=TRANSLATE THIS: only one column (bebop.demo.only_one_column) +bebop.demo.rightaligned_single_column=TRANSLATE THIS: right-aligned single column (bebop.demo.rightaligned_single_column) +bebop.demo.full_width_and_aligned_right=TRANSLATE THIS: full width and aligned right (bebop.demo.full_width_and_aligned_right) +bebop.demo.lonely_cell_on_last_row=TRANSLATE THIS: lonely cell on last row (bebop.demo.lonely_cell_on_last_row) +bebop.demo.this_is_the_blurb=TRANSLATE THIS: this is the Blurb (bebop.demo.this_is_the_blurb) +bebop.demo.a_static_label=TRANSLATE THIS: A static label (bebop.demo.a_static_label) +bebop.demo.this_should_be_full_width_too=TRANSLATE THIS: This should be full width too (bebop.demo.this_should_be_full_width_too) +bebop.demo.header=TRANSLATE THIS: Header (bebop.demo.header) +bebop.demo.left_component=TRANSLATE THIS: Left Component (bebop.demo.left_component) +bebop.demo.right_component=TRANSLATE THIS: Right Component (bebop.demo.right_component) +bebop.demo.ignored=TRANSLATE THIS: Ignored (bebop.demo.ignored) +bebop.demo.this_pane_talks_about_monocotyledons=TRANSLATE THIS: This pane talks about monocotyledons (bebop.demo.this_pane_talks_about_monocotyledons) +bebop.demo.this_pane_talks_about_dicotyledons=TRANSLATE THIS: This pane talks about dicotyledons (bebop.demo.this_pane_talks_about_dicotyledons) +bebop.demo.street=TRANSLATE THIS: Street (bebop.demo.street) +bebop.demo.country=TRANSLATE THIS: Country (bebop.demo.country) +bebop.demo.subscribe_to_our_mailing_list=TRANSLATE THIS: Subscribe to our mailing list (bebop.demo.subscribe_to_our_mailing_list) +bebop.demo.name=TRANSLATE THIS: Name: (bebop.demo.name) +bebop.demo.age=TRANSLATE THIS: Age: (bebop.demo.age) +bebop.demo.email_required=TRANSLATE THIS: Email (required): (bebop.demo.email_required) +bebop.demo.why_would_you_ever_want_to_subscribe_to_spam_=TRANSLATE THIS: Why would you ever want to subscribe to spam ? (bebop.demo.why_would_you_ever_want_to_subscribe_to_spam_) +bebop.demo.customize_your_sandwich=TRANSLATE THIS: Customize Your Sandwich (bebop.demo.customize_your_sandwich) +bebop.demo.protein=TRANSLATE THIS: Protein: (bebop.demo.protein) +bebop.demo.vitamins=TRANSLATE THIS: Vitamins: (bebop.demo.vitamins) +bebop.demo.sauce=TRANSLATE THIS: Sauce: (bebop.demo.sauce) +bebop.demo.payment_method=TRANSLATE THIS: Payment Method: (bebop.demo.payment_method) +bebop.demo.now_with_100_more_tofu_=TRANSLATE THIS: Now with 100% more tofu ! (bebop.demo.now_with_100_more_tofu_) +bebop.demo.delivery=TRANSLATE THIS: Delivery (bebop.demo.delivery) +bebop.demo.shipment_method=TRANSLATE THIS: Shipment Method: (bebop.demo.shipment_method) +bebop.demo.purchase=TRANSLATE THIS: Purchase (bebop.demo.purchase) +bebop.demo.animal_kingdom_little_lamb=TRANSLATE THIS: Animal Kingdom: Little Lamb (bebop.demo.animal_kingdom_little_lamb) +bebop.demo.workflow.process_name=TRANSLATE THIS: Process Name (bebop.demo.workflow.process_name) +bebop.demo.workflow.short_description=TRANSLATE THIS: Short Description (bebop.demo.workflow.short_description) +bebop.demo.workflow.name=TRANSLATE THIS: Name (bebop.demo.workflow.name) +bebop.demo.workflow.task=TRANSLATE THIS: Task (bebop.demo.workflow.task) +bebop.demo.workflow.description=TRANSLATE THIS: Description (bebop.demo.workflow.description) +bebop.demo.workflow.depends_on=TRANSLATE THIS: Depends on (bebop.demo.workflow.depends_on) +bebop.demo.workflow.h4emselect_process_to_view_detailsemh4=TRANSLATE THIS:

Select Process to View Details

(bebop.demo.workflow.h4emselect_process_to_view_detailsemh4) +bebop.demo.workflow.task_details=TRANSLATE THIS: Task details (bebop.demo.workflow.task_details) +bebop.demo.workflow.default_assignee_group=TRANSLATE THIS: Default assignee group (bebop.demo.workflow.default_assignee_group) +bebop.demo.workflow.dependencies=TRANSLATE THIS: Dependencies (bebop.demo.workflow.dependencies) +bebop.demo.workflow.add_dependency=TRANSLATE THIS: Add dependency (bebop.demo.workflow.add_dependency) +bebop.demo.workflow.none=TRANSLATE THIS: None (bebop.demo.workflow.none) +bebop.demo.workflow.h4workflow_templatesh4=TRANSLATE THIS:

Workflow Templates

(bebop.demo.workflow.h4workflow_templatesh4) +bebop.demo.workflow.add_template=TRANSLATE THIS: add template (bebop.demo.workflow.add_template) +bebop.page=TRANSLATE THIS: Page: (bebop.page) +bebop.previous=TRANSLATE THIS: Previous (bebop.previous) +bebop.next=TRANSLATE THIS: Next (bebop.next) +bebop.please_select_choice_from_the_list_on_the_left=TRANSLATE THIS: Please select choice from the list on the left (bebop.please_select_choice_from_the_list_on_the_left) +bebop.send_email_to_everybody=TRANSLATE THIS: Send email to everybody (bebop.send_email_to_everybody) +bebop.basic_item_metadata=TRANSLATE THIS: Basic Item Metadata (bebop.basic_item_metadata) +bebop.title=TRANSLATE THIS: Title: (bebop.title) +bebop.click_here=TRANSLATE THIS: click here (bebop.click_here) +bebop.demo.foo_is_null=TRANSLATE THIS: foo is null. (bebop.demo.foo_is_null) +bebop.demo.this_link_showshides_the_blurb=TRANSLATE THIS: This link shows/hides the Blurb (bebop.demo.this_link_showshides_the_blurb) +bebop.demo.no_action=TRANSLATE THIS: no action (bebop.demo.no_action) +bebop.event.default_text=TRANSLATE THIS: Default text (bebop.event.default_text) +bebop.event.call_no=TRANSLATE THIS: Call no. (bebop.event.call_no) +bebop.first_name=TRANSLATE THIS: First Name: (bebop.first_name) +bebop.last_name=TRANSLATE THIS: Last Name: (bebop.last_name) +bebop.hello_world=TRANSLATE THIS: Hello World (bebop.hello_world) +bebop.edit_the_foo_property=TRANSLATE THIS: Edit the Foo property (bebop.edit_the_foo_property) +bebop.table.=TRANSLATE THIS:   (bebop.table.) +bebop.the_table_is_empty=TRANSLATE THIS: The table is empty (bebop.the_table_is_empty) +bebop.util.some_text=TRANSLATE THIS: Some Text (bebop.util.some_text) +bebop.subject=TRANSLATE THIS: Subject (bebop.subject) +bebop.body=TRANSLATE THIS: Body (bebop.body) +bebop.are_you_sure=TRANSLATE THIS: Are you sure? (bebop.are_you_sure) +bebop.the_model_is_empty=TRANSLATE THIS: The Model is Empty (bebop.the_model_is_empty) +bebop.save=TRANSLATE THIS: Previous (bebop.save) +bebop.cancel=TRANSLATE THIS: Previous (bebop.cancel) +bebop.cancel.msg=TRANSLATE THIS: Previous (bebop.cancel.submission.msg) +bebop.parameter.unexpected_value_type=Unexpected value type: {0} +bebop.date.year.hint= +bebop.date.year.label= +bebop.hint.no_entry_yet=No information available yet. diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties index 02418549c..2a614ea0e 100644 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties @@ -196,3 +196,9 @@ ui.admin.user.email_addresses.delete=Delete ui.admin.user.primary_email.action=Action ui.admin.user.email_addresses.none=No additional email addresses ui.admin.user.email_addresses.add=Add email address +ui.admin.user.email_form.address=Email address +ui.admin.user.email_form.verified=Verified +ui.admin.user.email_form.bouncing=Bouncing +ui.admin.user.email_form.address.not_empty=Email address can't be empty. +ui.admin.user.email_addresses.delete.confirm=Are sure to delete this email address? +ui.admin.user_details.generate_password.confirm=Are you sure to reset this users password? diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties index e1f51a593..482a1faac 100644 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties @@ -196,3 +196,9 @@ ui.admin.user.email_addresses.delete=L\u00f6schen ui.admin.user.primary_email.action=Aktion ui.admin.user.email_addresses.none=Keine weiteren E-Mail-Adressen ui.admin.user.email_addresses.add=E-Mail-Adresse hinzuf\u00fcgen +ui.admin.user.email_form.address=E-Mail-Adresse +ui.admin.user.email_form.verified=Verifiziert +ui.admin.user.email_form.bouncing=Wird zur\u00fcckgewiesen +ui.admin.user.email_form.address.not_empty=Die E-Mail-Adresse darf nicht leer sein. +ui.admin.user.email_addresses.delete.confirm=Sind Sie sicher, dass Sie diese E-Mail-Adresse l\u00f6schen wollen? +ui.admin.user_details.generate_password.confirm=Sind Sie sicher, dass Sie das Passwort dieses Benutzers zur\u00fccksetzen wollen? diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties index 05aeb5742..ed90c9ddd 100755 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties @@ -169,3 +169,9 @@ ui.admin.user.email_addresses.delete=Delete ui.admin.user.primary_email.action=Action ui.admin.user.email_addresses.none=No additional email addresses ui.admin.user.email_addresses.add=Add email address +ui.admin.user.email_form.address=Email address +ui.admin.user.email_form.verified=Verified +ui.admin.user.email_form.bouncing=Bouncing +ui.admin.user.email_form.address.not_empty=Email address can't be empty. +ui.admin.user.email_addresses.delete.confirm=Are sure to delete this email address? +ui.admin.user_details.generate_password.confirm=Are you sure to reset this users password? diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties index 2afde016d..fccfbb4ed 100755 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties @@ -160,3 +160,9 @@ ui.admin.user.email_addresses.delete=Delete ui.admin.user.primary_email.action=Action ui.admin.user.email_addresses.none=No additional email addresses ui.admin.user.email_addresses.add=Add email address +ui.admin.user.email_form.address=Email address +ui.admin.user.email_form.verified=Verified +ui.admin.user.email_form.bouncing=Bouncing +ui.admin.user.email_form.address.not_empty=Email address can't be empty. +ui.admin.user.email_addresses.delete.confirm=Are sure to delete this email address? +ui.admin.user_details.generate_password.confirm=Are you sure to reset this users password?