/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.clerezza.platform.mail;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.ws.rs.core.MediaType;
import org.apache.clerezza.platform.typerendering.Renderer;
import org.apache.clerezza.platform.typerendering.RendererFactory;
import org.apache.clerezza.rdf.core.MGraph;
import org.apache.clerezza.rdf.core.Resource;
import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.access.TcManager;
import org.apache.clerezza.rdf.core.sparql.ParseException;
import org.apache.clerezza.rdf.core.sparql.QueryParser;
import org.apache.clerezza.rdf.core.sparql.ResultSet;
import org.apache.clerezza.rdf.core.sparql.query.SelectQuery;
import org.apache.clerezza.rdf.ontologies.FOAF;
import org.apache.clerezza.rdf.ontologies.PLATFORM;
import org.apache.clerezza.rdf.utils.GraphNode;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
/**
*
* Implementation of <code>MailMan</code> providing utility methods to send
* emails rendering GraphNodes
*
* @author mir, daniel
*/
@Component
@Service(MailMan.class)
public class MailManImpl implements MailMan {
@Reference
private TcManager tcManager;
@Reference
RendererFactory rendererFactory;
@Reference
MailSessionFactory mailSessionFactory;
private static String SYSTEM_GRAPH_URI = "urn:x-localinstance:/system.graph";
private UriRef systemGraphUri = new UriRef(SYSTEM_GRAPH_URI);
@Override
public void sendEmailToUser(final String fromUser, final String toUser,
final String subject, final String message) throws MessagingException {
try {
AccessController.checkPermission(new MailManPermission(fromUser, MailManPermission.SEND_FROM));
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws MessagingException {
InternetAddress fromAddress = getUserAddress(fromUser);
InternetAddress toAddress = getUserAddress(toUser);
sendEmail(fromAddress, toAddress, null, null, subject, message);
return null;
}
});
} catch (PrivilegedActionException ex) {
if (ex.getException() instanceof MessagingException) {
throw (MessagingException) ex.getException();
} else {
throw new RuntimeException(ex.getException());
}
}
}
@Override
public void sendEmailToUser(final String fromUser, final String toUser,
final String subject, final GraphNode graphNode,
final List<MediaType> acceptableMediaTypes, final String mode)
throws MessagingException {
try {
AccessController.checkPermission(
new MailManPermission(fromUser, MailManPermission.SEND_FROM));
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws MessagingException {
InternetAddress fromAddress = getUserAddress(fromUser);
InternetAddress toAddress = getUserAddress(toUser);
sendEmail(fromAddress, toAddress, null, null, subject, graphNode,
acceptableMediaTypes, mode);
return null;
}
});
} catch (PrivilegedActionException ex) {
if (ex.getException() instanceof MessagingException) {
throw (MessagingException) ex.getException();
} else {
throw new RuntimeException(ex.getException());
}
}
}
@Override
public void sendEmailToUsers(final String fromUser, final String[] toUsers,
final String subject, final String message) throws MessagingException {
try {
AccessController.checkPermission(
new MailManPermission(fromUser, MailManPermission.SEND_FROM));
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws MessagingException {
for (int i = 0; i < toUsers.length; i++) {
String toUser = toUsers[i];
sendEmailToUser(fromUser, toUser, subject, message);
}
return null;
}
});
} catch (PrivilegedActionException ex) {
if (ex.getException() instanceof MessagingException) {
throw (MessagingException) ex.getException();
} else {
throw new RuntimeException(ex.getException());
}
}
}
@Override
public void sendEmailToUsers(final String fromUser, final String[] toUsers,
final String subject, final GraphNode graphNode,
final List<MediaType> acceptableMediaTypes, final String mode)
throws MessagingException {
try {
AccessController.checkPermission(
new MailManPermission(fromUser, MailManPermission.SEND_FROM));
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws MessagingException {
for (int i = 0; i < toUsers.length; i++) {
String toUser = toUsers[i];
sendEmailToUser(fromUser, toUser, subject, graphNode,
acceptableMediaTypes, mode);
}
return null;
}
});
} catch (PrivilegedActionException ex) {
if (ex.getException() instanceof MessagingException) {
throw (MessagingException) ex.getException();
} else {
throw new RuntimeException(ex.getException());
}
}
}
@Override
public void sendEmail(InternetAddress from, InternetAddress to,
InternetAddress[] cc, InternetAddress[] bcc, String subject,
GraphNode graphNode, List<MediaType> acceptableMediaTypes,
String mode) throws MessagingException {
AccessController.checkPermission(
new MailManPermission("", MailManPermission.SEND_MAIL));
sendEmail(from, to, cc, bcc, subject, graphNode, null, acceptableMediaTypes,
mode);
}
@Override
public void sendEmail(InternetAddress from, InternetAddress to,
InternetAddress[] cc, InternetAddress[] bcc, String subject,
String message) throws MessagingException {
AccessController.checkPermission(
new MailManPermission("", MailManPermission.SEND_MAIL));
sendEmail(from, to, cc, bcc, subject, message, "text/plain", null, null);
}
@Override
public void sendEmail(InternetAddress from, InternetAddress to,
InternetAddress[] cc, InternetAddress[] bcc, String subject,
String message, String mediaType) throws MessagingException {
AccessController.checkPermission(
new MailManPermission("", MailManPermission.SEND_MAIL));
sendEmail(from, to, cc, bcc, subject, message, mediaType, null, null);
}
private void sendEmail(final InternetAddress from, final InternetAddress to,
final InternetAddress[] cc, final InternetAddress[] bcc,
final String subject, final Object content, final String mediaType,
final List<MediaType> acceptableMediaTypes, final String mode)
throws MessagingException {
final Session session = mailSessionFactory.getSession();
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws MessagingException {
MimeMessage mimeMessage = new MimeMessage(session);
Date date = new Date();
mimeMessage.setSentDate(date);
mimeMessage.setSubject(subject);
if (content instanceof GraphNode) {
GraphNode graphNode = (GraphNode) content;
Renderer renderer = rendererFactory.createRenderer(graphNode, mode,
acceptableMediaTypes == null ? Collections.singletonList(
MediaType.WILDCARD_TYPE) : acceptableMediaTypes);
if (renderer == null) {
throw new MessagingException("No renderer appropriate found");
}
mimeMessage.setDataHandler(
new GraphNodeDataHandler(graphNode, renderer));
} else {
mimeMessage.setContent(content, mediaType);
}
mimeMessage.setFrom(from);
if (to != null) {
mimeMessage.addRecipient(Message.RecipientType.TO, to);
}
if (cc != null) {
mimeMessage.addRecipients(Message.RecipientType.CC, cc);
}
if (bcc != null) {
mimeMessage.addRecipients(Message.RecipientType.BCC, bcc);
}
Transport.send(mimeMessage);
return null;
}
});
} catch (PrivilegedActionException ex) {
if (ex.getException() instanceof MessagingException) {
throw (MessagingException) ex.getException();
} else {
throw new RuntimeException(ex.getException());
}
}
}
private InternetAddress getUserAddress(String user) throws MessagingException {
MGraph systemGraph = tcManager.getMGraph(systemGraphUri);
final String queryString = "SELECT ?email WHERE { "
+ "?x " + FOAF.mbox + " ?email . "
+ "?x " + PLATFORM.userName + " \"" + user + "\" . "
+ "}";
try {
SelectQuery selectQuery = (SelectQuery) QueryParser.getInstance().parse(queryString);
ResultSet result = tcManager.executeSparqlQuery(selectQuery, systemGraph);
if (result.hasNext()) {
Resource email = result.next().get("email");
String emailString = ((UriRef) email).getUnicodeString();
//TODO should add personal name (if available) as well
return new InternetAddress(emailString.substring("mailto:".length()));
}
} catch (ParseException ex) {
throw new RuntimeException(ex);
} catch (AddressException ex) {
throw new RuntimeException(ex);
}
throw new MessagingException("No address found for user " + user);
}
}