/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2008-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.netmgt.ticketer.otrs; import java.rmi.RemoteException; import javax.xml.rpc.ServiceException; import org.opennms.core.utils.ThreadCategory; import org.opennms.integration.otrs.ticketservice.Article; import org.opennms.integration.otrs.ticketservice.ArticleCore; import org.opennms.integration.otrs.ticketservice.Credentials; import org.opennms.integration.otrs.ticketservice.TicketCore; import org.opennms.integration.otrs.ticketservice.TicketIDAndNumber; import org.opennms.integration.otrs.ticketservice.TicketServiceLocator; import org.opennms.integration.otrs.ticketservice.TicketServicePort_PortType; import org.opennms.integration.otrs.ticketservice.TicketStateUpdate; import org.opennms.integration.otrs.ticketservice.TicketWithArticles; import org.opennms.api.integration.ticketing.*; /** * OpenNMS Trouble Ticket Plugin API implementation for OTRS * * @author <a href="mailto:jonathan@opennms.org">Jonathan Sartin</a> * @version $Id: $ */ public class OtrsTicketerPlugin implements Plugin { private DefaultOtrsConfigDao m_configDao; private String m_endpoint; /** * <p>Constructor for OtrsTicketerPlugin.</p> */ public OtrsTicketerPlugin() { m_configDao = new DefaultOtrsConfigDao(); m_endpoint = m_configDao.getEndpoint(); } /** {@inheritDoc} */ public Ticket get(String ticketId) throws PluginException { TicketWithArticles ticketWithArticles = null; // don't try to get ticket if it's marked as not available Ticket opennmsTicket = new Ticket(); if (ticketId == null) { log().error("No OTRS ticketID available in OpenNMS Ticket"); throw new PluginException("No OTRS ticketID available in OpenNMS Ticket"); } else { TicketServicePort_PortType port = getTicketServicePort(m_endpoint); if (port != null) { long otrsTicketNumber = Long.parseLong(ticketId.trim()); Credentials creds = new Credentials(); creds.setUser(m_configDao.getUserName()); creds.setPass(m_configDao.getPassword()); // get the ticket from OTRS system try { ticketWithArticles = port.getByNumber(otrsTicketNumber, creds); } catch (RemoteException e) { log().error("Failed to retrieve OTRS ticket" + e); throw new PluginException("Failed to retrieve OTRS ticket"); } } } // add ticket basics from the OTRS ticket log().debug( "Adding Ticket details from OTRS ticket # " + ticketWithArticles.getTicket().getTicketNumber()); opennmsTicket.setId(ticketWithArticles.getTicket().getTicketNumber().toString()); opennmsTicket.setSummary(ticketWithArticles.getTicket().getTitle()); // Note that we user "Owner" from the OTRS ticket here. There is nothing to ensure // That this is a valid OpenNMS user opennmsTicket.setUser(ticketWithArticles.getTicket().getOwner()); opennmsTicket.setState(otrsToOpenNMSState(ticketWithArticles.getTicket().getStateID())); log().debug("Retrieved ticket state : " + otrsToOpenNMSState(ticketWithArticles.getTicket().getStateID())); // add all the article details from the OTRS ticket // this is not strictly essential as we have no way of viewing this atm. String opennmsTicketDetails = ""; for (Article article : ticketWithArticles.getArticles()) { log().debug( "Adding Article details from OTRS article ID " + article.getArticleID()); opennmsTicketDetails = opennmsTicketDetails + "\n" + "From: " + article.getFrom() + "\n" + "Subject: " + article.getSubject() + "\n" + "Body:\n" + article.getBody() + "\n"; } opennmsTicket.setDetails(opennmsTicketDetails); return opennmsTicket; } /** {@inheritDoc} */ public void saveOrUpdate(Ticket newTicket) throws PluginException { TicketIDAndNumber idAndNumber = null; TicketServicePort_PortType port = getTicketServicePort(m_endpoint); Ticket currentTicket = null; Credentials creds = new Credentials(); creds.setUser(m_configDao.getUserName()); creds.setPass(m_configDao.getPassword()); try { // If there's no external ID in the OpenNMS ticket, we need to create one if ((newTicket.getId() == null) ) { idAndNumber = newOTRSTicket(newTicket, port, creds); newTicket.setId(String.valueOf(idAndNumber.getTicketNumber())); log().debug("created new ticket: " + newTicket.getId()); newOTRSArticle(idAndNumber.getTicketNumber(), newTicket, port, creds); } else { currentTicket = get(newTicket.getId()); log().debug("updating existing ticket : " + currentTicket.getId()); if (currentTicket.getState() != newTicket.getState()) { updateOTRSState(newTicket, port, creds); updateOTRSArticle(Long.parseLong(currentTicket.getId()), newTicket, port, creds); } else { // There is no else at the moment // Tickets are _only_ updated with new state } } } catch (RemoteException e) { log().error("Failed to create or update OTRS ticket" + e); throw new PluginException("Failed to create or update OTRS ticket"); } } private void updateOTRSState(Ticket ticket, TicketServicePort_PortType port, Credentials creds) throws RemoteException { Integer otrsStateId = openNMSToOTRSState(ticket.getState()); TicketStateUpdate stateUpdate = new TicketStateUpdate(); stateUpdate.setStateID(otrsStateId); stateUpdate.setTicketNumber(Long.parseLong(ticket.getId())); if (ticket.getUser() != null) { stateUpdate.setUser(ticket.getUser()); } else { stateUpdate.setUser(m_configDao.getDefaultUser()); } log().debug("Updating ticket with new state"); log().debug("Ticket ID: " + ticket.getId()); log().debug("OpenNMS State: " + ticket.getState().toString()); log().debug("OTRS state: " + otrsStateId.toString()); port.ticketStateUpdate(stateUpdate, creds); } private TicketIDAndNumber newOTRSTicket(Ticket newTicket, TicketServicePort_PortType port, Credentials creds) throws RemoteException { TicketIDAndNumber idAndNumber = null; TicketCore newOtrsTicket = new TicketCore(); newOtrsTicket.setTitle(newTicket.getSummary()); // TODO: Could remove this once we have the userid reliably in the the ticket if (newTicket.getUser() != null) { newOtrsTicket.setUser(newTicket.getUser()); } else { newOtrsTicket.setUser(m_configDao.getDefaultUser()); } newOtrsTicket.setStateID(openNMSToOTRSState(newTicket.getState())); // All OTRS ticket fields from defaults newOtrsTicket.setQueue(m_configDao.getQueue()); newOtrsTicket.setPriority(m_configDao.getPriority()); newOtrsTicket.setLock(m_configDao.getLock()); newOtrsTicket.setOwnerID(m_configDao.getOwnerID()); idAndNumber = port.ticketCreate(newOtrsTicket, creds); return idAndNumber; } private void newOTRSArticle(Long otrsTicketNumber, Ticket newTicket, TicketServicePort_PortType port, Credentials creds) throws RemoteException { ArticleCore newOtrsArticle = new ArticleCore(); // All OTRS article fields from ticket log().debug("Adding a new article to ticket: " + otrsTicketNumber); newOtrsArticle.setBody(newTicket.getDetails()); newOtrsArticle.setTicketNumber(otrsTicketNumber); // TODO: Could remove this once we have the userid reliably in the the ticket newOtrsArticle.setFrom(m_configDao.getArticleFrom()); if (newTicket.getUser() != null) { newOtrsArticle.setUser(newTicket.getUser()); } else { newOtrsArticle.setUser(m_configDao.getDefaultUser()); } newOtrsArticle.setSubject(newTicket.getSummary()); // All OTRS article fields from defaults newOtrsArticle.setArticleType(m_configDao.getArticleType()); newOtrsArticle.setSenderType(m_configDao.getArticleSenderType()); newOtrsArticle.setContentType(m_configDao.getArticleContentType()); newOtrsArticle.setHistoryType(m_configDao.getArticleHistoryType()); newOtrsArticle.setHistoryComment(m_configDao.getArticleHistoryComment()); port.articleCreate(newOtrsArticle, creds); } private void updateOTRSArticle(Long otrsTicketNumber, Ticket newTicket, TicketServicePort_PortType port, Credentials creds) throws RemoteException { ArticleCore newOtrsArticle = new ArticleCore(); // All OTRS article fields from ticket log().debug("Adding a new article to ticket: " + otrsTicketNumber); switch (newTicket.getState()) { case OPEN: // ticket is new newOtrsArticle.setBody(m_configDao.getTicketOpenedMessage()); break; case CANCELLED: // not sure how often we see this newOtrsArticle.setBody(m_configDao.getTicketCancelledMessage()); break; case CLOSED: // closed successful newOtrsArticle.setBody(m_configDao.getTicketClosedMessage()); break; default: log().debug("No valid OpenNMS state on ticket"); newOtrsArticle.setBody(m_configDao.getTicketUpdatedMessage()); } newOtrsArticle.setTicketNumber(otrsTicketNumber); // TODO: Could remove this once we have the userid reliably in the the ticket newOtrsArticle.setFrom(m_configDao.getArticleFrom()); if (newTicket.getUser() != null) { newOtrsArticle.setUser(newTicket.getUser()); } else { newOtrsArticle.setUser(m_configDao.getDefaultUser()); } newOtrsArticle.setSubject(m_configDao.getArticleUpdateSubject()); // All OTRS article fields from defaults newOtrsArticle.setArticleType(m_configDao.getArticleType()); newOtrsArticle.setSenderType(m_configDao.getArticleSenderType()); newOtrsArticle.setContentType(m_configDao.getArticleContentType()); newOtrsArticle.setHistoryType(m_configDao.getArticleHistoryType()); newOtrsArticle.setHistoryComment(m_configDao.getArticleHistoryComment()); port.articleCreate(newOtrsArticle, creds); } /** * Convenience method for converting OpenNMS enumerated ticket states to * OTRS ticket StateID. * * TODO: Convert this to something parameterised * * @param state * @return an Integer representing the OTRS StateID. */ private Integer openNMSToOTRSState(Ticket.State state) { Integer otrsStateId; log().debug("getting otrs state from OpenNMS State " + state.toString()); switch (state) { case OPEN: // ticket is new otrsStateId = m_configDao.getOpenStateId(); break; case CANCELLED: // not sure how often we see this otrsStateId = m_configDao.getCancelledStateId(); break; case CLOSED: // closed successful otrsStateId = m_configDao.getClosedStateId(); break; default: log().debug("No valid OpenNMS state on ticket"); otrsStateId = m_configDao.getOpenStateId(); } log().debug("OpenNMS state was " + state.toString()); log().debug("setting OTRS state ID to " + otrsStateId.toString()); return otrsStateId; } /** * Convenience method for converting OTRS ticket StateID to * OpenNMS enumerated ticket states. * * @param otrsStateID * @return the converted <code>org.opennms.netmgt.ticketd.Ticket.State</code> */ private Ticket.State otrsToOpenNMSState(Integer otrsStateId ) { Ticket.State openNMSState; if (m_configDao.getValidOpenStateId().contains(otrsStateId)) { log().debug("OTRS state ID " + otrsStateId.toString() + " matched OpenNMS state Open"); openNMSState = Ticket.State.OPEN; } else if (m_configDao.getValidClosedStateId().contains(otrsStateId)) { log().debug("OTRS state ID " + otrsStateId.toString() + " matched OpenNMS state Closed"); openNMSState = Ticket.State.CLOSED; } else if (m_configDao.getValidCancelledStateId().contains(otrsStateId)) { log().debug("OTRS state ID " + otrsStateId.toString() + " matched OpenNMS state Cancelled"); openNMSState = Ticket.State.CANCELLED; } else { log().debug("OTRS state ID " + otrsStateId.toString() + " has no matching OpenNMS state"); // we dont know what it is, so default to keeping it open. openNMSState = Ticket.State.OPEN; } return openNMSState; } /** * Convenience method for initialising the ticketServicePort and correctly setting the endpoint. * * @return TicketServicePort to connect to the remote service. */ private TicketServicePort_PortType getTicketServicePort(String endpoint) throws PluginException { TicketServiceLocator service = new TicketServiceLocator(); service.setTicketServicePortEndpointAddress(endpoint); TicketServicePort_PortType port = null; try { port = service.getTicketServicePort(); } catch (ServiceException e) { log().error("Failed initialzing OTRS TicketServicePort" + e); throw new PluginException("Failed initialzing OTRS TicketServicePort"); } return port; } /** * Covenience logging. * * @return a log4j Category for this class */ ThreadCategory log() { return ThreadCategory.getInstance(getClass()); } /** * <p>getEndpoint</p> * * @return a {@link java.lang.String} object. */ public String getEndpoint() { return m_endpoint; } /** * <p>setEndpoint</p> * * @param endpoint a {@link java.lang.String} object. */ public void setEndpoint(String endpoint) { m_endpoint = endpoint; } }