org.sipfoundry.voicemail.mailbox.AbstractMailboxManager.java Source code

Java tutorial

Introduction

Here is the source code for org.sipfoundry.voicemail.mailbox.AbstractMailboxManager.java

Source

/**
 *
 *
 * Copyright (c) 2011 eZuce, Inc. All rights reserved.
 * Contributed to SIPfoundry under a Contributor Agreement
 *
 * This software is free software; you can redistribute it and/or modify it under
 * the terms of the Affero General Public License (AGPL) as published by the
 * Free Software Foundation; either version 3 of the License, or (at your option)
 * any later version.
 *
 * This software is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 */
package org.sipfoundry.voicemail.mailbox;

import java.io.File;
import java.io.IOException;
import java.io.SequenceInputStream;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.sipfoundry.commons.userdb.User;
import org.sipfoundry.sipxivr.email.Emailer;
import org.sipfoundry.sipxivr.rest.RestfulRequest;
import org.sipfoundry.voicemail.Mwi;
import org.sipfoundry.voicemail.mailbox.MessageDescriptor.Priority;

public abstract class AbstractMailboxManager implements MailboxManager {

    static final Logger LOG = Logger.getLogger("org.sipfoundry.sipxivr");
    protected String m_mailstoreDirectory;
    protected String m_promptsDirectory;
    protected String m_operatorAddr;
    protected Mwi m_mwi;
    private String m_configUrl;
    private String m_secret;
    private Emailer m_emailer;
    private String m_identity;
    private String m_audioFormat;
    private String m_altAudioFormat;

    protected abstract VmMessage saveTempMessageInStorage(User destUser, TempMessage message,
            MessageDescriptor descriptor, Folder storageFolder, String messageId);

    protected abstract VmMessage saveTempMessageInStorage(User destUser, TempMessage message,
            MessageDescriptor descriptor, String messageId);

    protected abstract File getTempFolder(String username);

    protected abstract VmMessage copyMessage(String newMessageId, User destUser, TempMessage message);

    protected abstract VmMessage forwardMessage(VmMessage originalMessage, TempMessage comments,
            MessageDescriptor descriptor, User destUser, String newMessageId);

    @Override
    public final TempMessage createTempMessage(String username, String fromUri, boolean audio) {
        return createTempMessage(username, fromUri, m_audioFormat, audio);
    }

    @Override
    public final TempMessage createTempMessage(String username, String fromUri, String extension, boolean audio) {
        try {
            String audioPath = null;
            if (audio) {
                File audioFile = File.createTempFile("temp_recording_", "." + extension, getTempFolder(username));
                audioPath = audioFile.getPath();
            }
            return new TempMessage(username, audioPath, fromUri, Priority.NORMAL, null);
        } catch (IOException e) {
            throw new RuntimeException("Cannot create temp recording file", e);
        }
    }

    @Override
    public final void deleteTempMessage(TempMessage message) {
        FileUtils.deleteQuietly(new File(message.getTempPath()));
    }

    @Override
    public final void storeInInbox(User destUser, TempMessage message) {
        store(destUser, Folder.INBOX, message, VOICEMAIL_SUBJECT);
    }

    @Override
    public final void store(User destUser, Folder folder, TempMessage message, String subject) {
        // Not this one, just delete any temp file
        if (!message.isToBeStored()) {
            FileUtils.deleteQuietly(new File(message.getTempPath()));
            return;
        }

        if (!message.isStored()) {
            String messageId = nextMessageId(m_mailstoreDirectory + "/..");
            VmMessage savedMessage = saveTempMessageInStorage(destUser, message,
                    createMessageDescriptor(destUser.getUserName(), message, messageId, subject,
                            destUser.getIdentity()),
                    folder, messageId);
            message.setSavedMessageId(messageId);
            message.setStored(true);
            if (savedMessage != null) {
                //Make sure to set folder after the message was correctly saved
                savedMessage.setParentFolder(folder);
                m_emailer.queueVm2Email(destUser, savedMessage);
            }
        }
    }

    @Override
    public final void copyMessage(User destUser, TempMessage message) {
        String newMessageId = nextMessageId(m_mailstoreDirectory + "/..");
        VmMessage savedMessage = copyMessage(newMessageId, destUser, message);
        if (savedMessage != null) {
            //the method applies only to voicemails - so the folder where the message is saved is always INBOX
            savedMessage.setParentFolder(Folder.INBOX);
            m_emailer.queueVm2Email(destUser, savedMessage);
        }
    }

    @Override
    public void forwardMessage(User destUser, VmMessage message, TempMessage comments) {
        String newMessageId = nextMessageId(m_mailstoreDirectory + "/..");
        MessageDescriptor descriptor = createMessageDescriptor(destUser.getUserName(), comments, newMessageId,
                destUser.getIdentity());
        long totalDuration = descriptor.getDurationSecsLong() + message.getDescriptor().getDurationSecsLong();
        descriptor.setDurationSecs(totalDuration);
        descriptor.setSubject("Fwd:Voice Message " + newMessageId);
        VmMessage savedMessage = forwardMessage(message, comments, descriptor, destUser, newMessageId);
        if (savedMessage != null) {
            //the method applies only to voicemails - so the folder where the message is saved is always INBOX
            savedMessage.setParentFolder(Folder.INBOX);
            m_emailer.queueVm2Email(destUser, savedMessage);
        }
        comments.setSavedMessageId(newMessageId);
        comments.setStored(true);
    }

    @Override
    public final void saveActiveGreeting(User user, GreetingType type) {
        // only preferences updated here are the active greeing and that is done
        // via a sipXconfig REST call

        // /sipxconfig/rest/my/mailbox/200/preferences/activegreeting/standard

        RestfulRequest rr = new RestfulRequest(
                m_configUrl + "/sipxconfig/rest/my/mailbox/" + user.getUserName() + "/preferences/activegreeting/",
                user.getUserName(), m_secret);

        try {
            if (rr.put(type.getId())) {
                LOG.info("Mailbox::writeMailboxPreferences:change Greeting " + user.getUserName()
                        + " greeting changed.");
            }
        } catch (Exception e) {
            LOG.info("Mailbox::writeMailboxPreferences:change Greeting " + user.getUserName() + " failed: "
                    + e.getMessage());
        }
    }

    @Override
    public final boolean changePin(User destUser, String newPin) {
        try {
            // Use sipXconfig's RESTful interface to change the PIN
            RestfulRequest rr = new RestfulRequest(m_configUrl + "/sipxconfig/rest/my/voicemail/pin/",
                    destUser.getUserName(), m_secret);
            return rr.put(newPin);
        } catch (Exception e) {
            LOG.error("Retrieve::voicemailOptions new pin trouble", e);
        }
        return false;
    }

    @Override
    public final boolean manageSpecialMode(User user, boolean enable) {
        try {
            // Use sipXconfig's RESTful interface to change the special mode
            RestfulRequest rr = new RestfulRequest(m_configUrl + "/sipxconfig/rest/auto-attendant/specialmode",
                    user.getUserName(), m_secret);
            if (enable) {
                return rr.put(null);
            } else {
                return rr.delete();
            }
        } catch (Exception e) {
            LOG.error("Retrieve::adminOptions:specialmode trouble", e);
        }
        return false;
    }

    @Override
    public void migrate(String path) {
        // do nothing, classes that extends this should provide a mean for migrating voicemails
    }

    private MessageDescriptor createMessageDescriptor(String destUser, TempMessage message, String messageId,
            String subject, String identity) {
        MessageDescriptor descriptor = new MessageDescriptor();
        descriptor.setId(identity);
        descriptor.setFromUri(message.getFromUri());
        descriptor.setDurationSecs(message.getDuration());
        descriptor.setTimestamp(message.getTimestamp());
        descriptor.setSubject(subject + messageId);
        descriptor.setPriority(message.getPriority());
        if (message.getOtherRecipients() != null) {
            for (User recipient : message.getOtherRecipients()) {
                if (!recipient.getUserName().equals(destUser)) {
                    descriptor.addOtherRecipient(recipient.getUserName());
                }
            }
        }
        descriptor.setAudioFormat(getAudioFormat());
        return descriptor;
    }

    //Creates VOICEMAIL message descriptors only
    private MessageDescriptor createMessageDescriptor(String destUser, TempMessage message, String messageId,
            String identity) {
        return createMessageDescriptor(destUser, message, messageId, VOICEMAIL_SUBJECT, identity);
    }

    /**
     * Generate the next message Id static synchronized as it's machine wide
     *
     * @param directory which holds the messageid.txt file
     */
    private synchronized String nextMessageId(String directory) {
        File midFile = new File(directory, "messageid.txt");
        String messageIdFilePath = midFile.getPath();
        long numericMessageId;
        String messageId;
        if (!midFile.exists()) {
            numericMessageId = 1;
            String format = m_identity + "%08d";
            messageId = String.format(format, numericMessageId);
            numericMessageId++;
            try {
                FileUtils.writeStringToFile(midFile, String.format(format, numericMessageId));
            } catch (IOException e) {
                LOG.error("Message::nextMessageId cannot write " + messageIdFilePath, e);
                throw new RuntimeException(e);
            }
            return messageId;
        }

        try {
            // The messageid in the file is the NEXT one
            messageId = FileUtils.readFileToString(midFile);
            numericMessageId = Long.parseLong(StringUtils.deleteWhitespace(messageId));
        } catch (IOException e) {
            LOG.error("Message::nextMessageId cannot read " + messageIdFilePath, e);
            throw new RuntimeException(e);
        }
        // Increment message id, store for another day
        numericMessageId++;
        try {
            FileUtils.writeStringToFile(midFile, String.valueOf(numericMessageId));
        } catch (IOException e) {
            LOG.error("Message::nextMessageId cannot write " + messageIdFilePath, e);
            throw new RuntimeException(e);
        }

        return messageId;
    }

    protected Folder getFolderFromName(String name) {
        if (Folder.INBOX.toString().equals(name)) {
            return Folder.INBOX;
        }
        if (Folder.SAVED.toString().equals(name)) {
            return Folder.SAVED;
        }
        if (Folder.DELETED.toString().equals(name)) {
            return Folder.DELETED;
        }
        if (Folder.CONFERENCE.toString().equals(name)) {
            return Folder.CONFERENCE;
        }
        return null;
    }

    protected String getGreetingTypeName(GreetingType type) {
        switch (type) {
        case STANDARD:
            return String.format("standard.%s", m_audioFormat);
        case OUT_OF_OFFICE:
            return String.format("outofoffice.%s", m_audioFormat);
        case EXTENDED_ABSENCE:
            return String.format("extendedabs.%s", m_audioFormat);
        default:
            return null;
        }
    }

    protected void concatAudio(File newFile, File orig1, File orig2) throws Exception {
        String operation = "dunno";
        AudioInputStream clip1 = null;
        AudioInputStream clip2 = null;
        AudioInputStream concatStream = null;
        try {
            operation = "getting AudioInputStream from " + orig1.getPath();
            clip1 = AudioSystem.getAudioInputStream(orig1);
            operation = "getting AudioInputStream from " + orig2.getPath();
            clip2 = AudioSystem.getAudioInputStream(orig2);

            operation = "building SequnceInputStream";
            concatStream = new AudioInputStream(new SequenceInputStream(clip1, clip2), clip1.getFormat(),
                    clip1.getFrameLength() + clip2.getFrameLength());

            operation = "writing SequnceInputStream to " + newFile.getPath();
            AudioSystem.write(concatStream, AudioFileFormat.Type.WAVE, newFile);
            LOG.info("VmMessage::concatAudio created combined file " + newFile.getPath());
        } catch (Exception e) {
            String trouble = "VmMessage::concatAudio Problem while " + operation;
            throw new Exception(trouble, e);
        } finally {
            IOUtils.closeQuietly(clip1);
            IOUtils.closeQuietly(clip2);
            IOUtils.closeQuietly(concatStream);
        }
    }

    public String getNameFile() {
        return String.format("name.%s", m_audioFormat);
    }

    public String getPromptFile() {
        return String.format("customautoattendant-%d.%s", System.currentTimeMillis() / 1000, m_audioFormat);
    }

    public void setMailstoreDirectory(String dir) {
        m_mailstoreDirectory = dir;
    }

    public void setPromptsDirectory(String dir) {
        m_promptsDirectory = dir;
    }

    public void setOperatorAddr(String operatorAddr) {
        m_operatorAddr = operatorAddr;
    }

    public void setConfigUrl(String configUrl) {
        m_configUrl = configUrl;
    }

    public void setSecret(String secret) {
        m_secret = secret;
    }

    public void setEmailer(Emailer emailer) {
        m_emailer = emailer;
    }

    public void setMwiManager(Mwi mwiManager) {
        m_mwi = mwiManager;
    }

    public void setIvrIdentity(String identity) {
        m_identity = identity;
    }

    public void setAudioFormat(String format) {
        m_audioFormat = format;
        if (m_audioFormat.equals("mp3")) {
            m_altAudioFormat = "wav";
        } else {
            m_altAudioFormat = "mp3";
        }
    }

    public String getAudioFormat() {
        return m_audioFormat;
    }

    public String getAltAudioFormat() {
        return m_altAudioFormat;
    }

}