diff --git a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/identity/event/IHttpdXmppMessage.java b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/identity/event/IHttpXmppMessage.java similarity index 85% rename from cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/identity/event/IHttpdXmppMessage.java rename to cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/identity/event/IHttpXmppMessage.java index 6e8b5b1dc0..73aa76554a 100644 --- a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/identity/event/IHttpdXmppMessage.java +++ b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/identity/event/IHttpXmppMessage.java @@ -23,7 +23,7 @@ import java.util.regex.Pattern; /** * Used to store constants that are used to validate, analyze, and parse status - * and configuration messages associated with the AWIPS II httpd collaboration + * and configuration messages associated with the AWIPS II http collaboration * server. * *
@@ -34,6 +34,8 @@ import java.util.regex.Pattern; * ------------ ---------- ----------- -------------------------- * Aug 7, 2012 bkowal Initial creation * Dec 18, 2013 2562 bclement removed preamble from patterns + * Feb 17, 2014 2756 bclement removed URL regex that was too specific + * renamed to remove httpd reference * ** @@ -41,7 +43,7 @@ import java.util.regex.Pattern; * @version 1.0 */ -public interface IHttpdXmppMessage { +public interface IHttpXmppMessage { // Constant Strings public static final String URL_PARAMETER_NAME = "sessionDataHttpURL"; @@ -49,8 +51,6 @@ public interface IHttpdXmppMessage { static final String SUFFIX_REGEX = " : .+"; - static final String COLLABORATION_URL_REGEX = "http://.+:[1-9][0-9]*/session_data/"; - // Regex Patterns public static final Pattern configErrorPattern = Pattern .compile(ERROR_PARAMETER_NAME + SUFFIX_REGEX); @@ -58,6 +58,4 @@ public interface IHttpdXmppMessage { public static final Pattern configURLPattern = Pattern .compile(URL_PARAMETER_NAME + SUFFIX_REGEX); - public static final Pattern urlPattern = Pattern - .compile(COLLABORATION_URL_REGEX); } diff --git a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/session/PeerToPeerCommHelper.java b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/session/PeerToPeerCommHelper.java index fe22817887..4ebba1f156 100644 --- a/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/session/PeerToPeerCommHelper.java +++ b/cave/com.raytheon.uf.viz.collaboration.comm/src/com/raytheon/uf/viz/collaboration/comm/provider/session/PeerToPeerCommHelper.java @@ -19,6 +19,9 @@ **/ package com.raytheon.uf.viz.collaboration.comm.provider.session; +import java.net.URI; +import java.net.URL; + import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; @@ -27,9 +30,10 @@ import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.viz.collaboration.comm.Activator; +import com.raytheon.uf.viz.collaboration.comm.identity.CollaborationException; import com.raytheon.uf.viz.collaboration.comm.identity.ISession; +import com.raytheon.uf.viz.collaboration.comm.identity.event.IHttpXmppMessage; import com.raytheon.uf.viz.collaboration.comm.identity.event.IHttpdCollaborationConfigurationEvent; -import com.raytheon.uf.viz.collaboration.comm.identity.event.IHttpdXmppMessage; import com.raytheon.uf.viz.collaboration.comm.identity.event.ITextMessageEvent; import com.raytheon.uf.viz.collaboration.comm.identity.user.IUser; import com.raytheon.uf.viz.collaboration.comm.provider.SessionPayload; @@ -38,6 +42,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.Tools; import com.raytheon.uf.viz.collaboration.comm.provider.event.ChatMessageEvent; import com.raytheon.uf.viz.collaboration.comm.provider.event.HttpdCollaborationConfigurationEvent; import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter; +import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId; /** * Listens for peer to peer messages and routes them appropriately. @@ -54,6 +59,8 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter; * data now in packet extension * Dec 19, 2013 2563 bclement removed wait for HTTP config, added reset * Feb 13, 2014 2751 bclement changed IQualifiedID objects to IUser + * Feb 17, 2014 2756 bclement null check for message from field + * moved url validation from regex to java utility * * * @@ -67,7 +74,7 @@ public class PeerToPeerCommHelper implements PacketListener { .getHandler(PeerToPeerCommHelper.class); private static volatile String httpServer; - + /** * Get HTTP server address. This value will be updated if the server sends * new HTTP configuration. If this address is null, the server most likely @@ -101,7 +108,14 @@ public class PeerToPeerCommHelper implements PacketListener { public void processPacket(Packet packet) { if (packet instanceof Message) { Message msg = (Message) packet; - if (IDConverter.isFromRoom(msg.getFrom())) { + String fromStr = msg.getFrom(); + if (fromStr == null) { + // from server + UserId account = CollaborationConnection.getConnection() + .getUser(); + fromStr = account.getHost(); + } + if (IDConverter.isFromRoom(fromStr)) { // venues will have their own listeners return; } @@ -204,11 +218,11 @@ public class PeerToPeerCommHelper implements PacketListener { */ private void handleConfiguration(String body) { // Determine if an error has occurred. - if (IHttpdXmppMessage.configErrorPattern.matcher(body).matches()) { + if (IHttpXmppMessage.configErrorPattern.matcher(body).matches()) { statusHandler.handle( UFStatus.Priority.ERROR, this.getCollaborationConfigurationParameterValue(body, - IHttpdXmppMessage.ERROR_PARAMETER_NAME) + IHttpXmppMessage.ERROR_PARAMETER_NAME) + ". Shared Display Sessions have been disabled."); this.disableSharedDisplaySession(); // terminate execution @@ -216,7 +230,7 @@ public class PeerToPeerCommHelper implements PacketListener { } // Validate the configuration. - if (IHttpdXmppMessage.configURLPattern.matcher(body).matches() == false) { + if (IHttpXmppMessage.configURLPattern.matcher(body).matches() == false) { statusHandler .handle(UFStatus.Priority.PROBLEM, "Received invalid configuration from openfire. Shared Display Sessions have been disabled."); @@ -225,24 +239,32 @@ public class PeerToPeerCommHelper implements PacketListener { } // Remove the parameter name. - String httpdCollaborationURL = this + String httpCollaborationURL = this .getCollaborationConfigurationParameterValue(body, - IHttpdXmppMessage.URL_PARAMETER_NAME); + IHttpXmppMessage.URL_PARAMETER_NAME); // validate the url. - if (IHttpdXmppMessage.urlPattern.matcher(httpdCollaborationURL) - .matches() == false) { + try { + URL u = new URL(httpCollaborationURL); + URI uri = u.toURI(); + if (!uri.getScheme().equalsIgnoreCase("http")) { + throw new CollaborationException( + "Provided URL doesn't use the HTTP scheme"); + } + } catch (Exception e) { statusHandler.handle(UFStatus.Priority.PROBLEM, "Received an invalid http url from openfire - " - + httpdCollaborationURL - + ". Shared Display Sessions have been disabled."); + + httpCollaborationURL + + ". Shared Display Sessions have been disabled.", + e); this.disableSharedDisplaySession(); return; } - httpServer = httpdCollaborationURL; + + httpServer = httpCollaborationURL; // configuration is valid; publish it. IHttpdCollaborationConfigurationEvent configurationEvent = new HttpdCollaborationConfigurationEvent( - httpdCollaborationURL); + httpCollaborationURL); manager.postEvent(configurationEvent); } diff --git a/cave/com.raytheon.uf.viz.collaboration.display/src/com/raytheon/uf/viz/collaboration/display/rsc/telestrator/CollaborationDrawingResource.java b/cave/com.raytheon.uf.viz.collaboration.display/src/com/raytheon/uf/viz/collaboration/display/rsc/telestrator/CollaborationDrawingResource.java index 71f3c8d99a..ab7d0a6a6f 100644 --- a/cave/com.raytheon.uf.viz.collaboration.display/src/com/raytheon/uf/viz/collaboration/display/rsc/telestrator/CollaborationDrawingResource.java +++ b/cave/com.raytheon.uf.viz.collaboration.display/src/com/raytheon/uf/viz/collaboration/display/rsc/telestrator/CollaborationDrawingResource.java @@ -62,6 +62,7 @@ import com.vividsolutions.jts.geom.Coordinate; * ------------ ---------- ----------- -------------------------- * May 23, 2012 mschenke Initial creation * Jan 30, 2014 2698 bclement changed UserId to VenueParticipant + * Feb 13, 2014 2751 bclement VenueParticipant refactor * * * diff --git a/cave/com.raytheon.uf.viz.collaboration.display/src/com/raytheon/uf/viz/collaboration/display/storage/CollaborationObjectEventStorage.java b/cave/com.raytheon.uf.viz.collaboration.display/src/com/raytheon/uf/viz/collaboration/display/storage/CollaborationObjectEventStorage.java index a23710c7cd..e9310eb3b5 100644 --- a/cave/com.raytheon.uf.viz.collaboration.display/src/com/raytheon/uf/viz/collaboration/display/storage/CollaborationObjectEventStorage.java +++ b/cave/com.raytheon.uf.viz.collaboration.display/src/com/raytheon/uf/viz/collaboration/display/storage/CollaborationObjectEventStorage.java @@ -19,18 +19,25 @@ **/ package com.raytheon.uf.viz.collaboration.display.storage; +import java.io.ByteArrayInputStream; import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.message.BasicHeader; import com.raytheon.uf.common.comm.HttpClient; import com.raytheon.uf.common.comm.HttpClient.HttpClientResponse; @@ -49,7 +56,9 @@ import com.raytheon.uf.viz.remote.graphics.events.DisposeObjectEvent; import com.raytheon.uf.viz.remote.graphics.events.ICreationEvent; /** - * Class responsible for object event storage. Will persist/retrieve objects + * Class responsible for object event storage. Will persist/retrieve objects. + * When listing remote directories, this client uses the HTTP Accepts header to + * prefer XML format, but also accepts HTML. * *
* @@ -58,6 +67,7 @@ import com.raytheon.uf.viz.remote.graphics.events.ICreationEvent; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 20, 2012 mschenke Initial creation + * Feb 17, 2014 2756 bclement added xml parsing for HTTP directory listing * ** @@ -90,12 +100,20 @@ public class CollaborationObjectEventStorage implements return persistance; } + public static final String ACCEPTS_HEADER = "Accepts"; + + public static final String XML_CONTENT_TYPE = "text/xml"; + + public static final String HTML_CONTENT_TYPE = "text/html"; + private String sessionDataURL; private HttpClient client; private int displayId; + private final XMLInputFactory staxFactory = XMLInputFactory.newInstance(); + private CollaborationObjectEventStorage(ISharedDisplaySession session, int displayId) { this.displayId = displayId; @@ -116,6 +134,7 @@ public class CollaborationObjectEventStorage implements public IPersistedEvent persistEvent(AbstractDispatchingObjectEvent event) throws CollaborationException { if (event instanceof ICreationEvent) { + // TODO this is for pre 14.3 compatibility createFolder(String.valueOf(event.getObjectId())); } else if (event instanceof DisposeObjectEvent) { // Do not delete anything off the server, users may still be @@ -205,6 +224,13 @@ public class CollaborationObjectEventStorage implements } } + /** + * Execute get request for object stored at event's resource path + * + * @param event + * @return null if object was deleted + * @throws CollaborationException + */ private CollaborationHttpPersistedObject retreiveStoredObject( CollaborationHttpPersistedEvent event) throws CollaborationException { @@ -213,9 +239,10 @@ public class CollaborationObjectEventStorage implements HttpClientResponse response = executeRequest(get); if (isSuccess(response.code)) { try { - CollaborationHttpPersistedObject dataObject = (CollaborationHttpPersistedObject) SerializationUtil - .transformFromThrift(CompressionUtil - .uncompress(response.data)); + CollaborationHttpPersistedObject dataObject = SerializationUtil + .transformFromThrift( + CollaborationHttpPersistedObject.class, + CompressionUtil.uncompress(response.data)); if (dataObject != null) { dataObject.dataSize = response.data.length; } @@ -244,6 +271,8 @@ public class CollaborationObjectEventStorage implements throws CollaborationException { String objectPath = objectId + "/"; HttpGet get = new HttpGet(sessionDataURL + objectPath); + get.addHeader(new BasicHeader(ACCEPTS_HEADER, XML_CONTENT_TYPE + "," + + HTML_CONTENT_TYPE)); HttpClientResponse response = executeRequest(get); if (isSuccess(response.code) == false) { if (isNotExists(response.code)) { @@ -252,38 +281,21 @@ public class CollaborationObjectEventStorage implements throw new CollaborationException("Error retrieving object (" + objectId + ") events, received code: " + response.code); } - CollaborationHttpPersistedEvent event = new CollaborationHttpPersistedEvent(); - List
* @@ -33,6 +33,7 @@ import java.util.regex.Pattern; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 8, 2013 2539 bclement Initial creation + * Feb 14, 2014 2756 bclement moved to common http from ogc common * ** diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/http/AcceptHeaderValue.java b/edexOsgi/com.raytheon.uf.common.http/src/com/raytheon/uf/common/http/AcceptHeaderValue.java similarity index 94% rename from edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/http/AcceptHeaderValue.java rename to edexOsgi/com.raytheon.uf.common.http/src/com/raytheon/uf/common/http/AcceptHeaderValue.java index 1df92f26d9..091ce531c1 100644 --- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/http/AcceptHeaderValue.java +++ b/edexOsgi/com.raytheon.uf.common.http/src/com/raytheon/uf/common/http/AcceptHeaderValue.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.uf.edex.ogc.common.http; +package com.raytheon.uf.common.http; /** * Represents a single HTTP accept(-encoding) header encoding with weight value @@ -29,6 +29,7 @@ package com.raytheon.uf.edex.ogc.common.http; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 8, 2013 2539 bclement Initial creation + * Feb 14, 2014 2756 bclement moved to common http from ogc common * * * diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/http/MimeType.java b/edexOsgi/com.raytheon.uf.common.http/src/com/raytheon/uf/common/http/MimeType.java similarity index 89% rename from edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/http/MimeType.java rename to edexOsgi/com.raytheon.uf.common.http/src/com/raytheon/uf/common/http/MimeType.java index 33f50f5c9b..4f2a8ced8c 100644 --- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/http/MimeType.java +++ b/edexOsgi/com.raytheon.uf.common.http/src/com/raytheon/uf/common/http/MimeType.java @@ -7,7 +7,7 @@ * in and to this copyrighted software are as specified in DFARS * 252.227-7014 which was made part of the above contract. */ -package com.raytheon.uf.edex.ogc.common.http; +package com.raytheon.uf.common.http; import java.util.Collections; import java.util.LinkedHashMap; @@ -18,7 +18,7 @@ import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; /** - * Data object representing a MIME type used in service requests + * Data object representing a MIME type used in http requests * *
* @@ -27,6 +27,7 @@ import org.apache.commons.lang.StringUtils; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Oct 29, 2012 bclement Initial creation + * Feb 14, 2014 2756 bclement moved to common http from ogc common * ** @@ -50,6 +51,9 @@ public class MimeType { private static final Pattern PARAM_PATTERN = Pattern.compile(";\\s*(" + TOKEN_CLASS + "+)=(" + TOKEN_CLASS + "+|\"\\S+\")"); + /** + * @param mime + */ public MimeType(String mime){ Matcher m = TYPE_PATTERN.matcher(mime); if (m.matches()) { @@ -70,6 +74,12 @@ public class MimeType { } } + /** + * Parse parameter string into name/value pairs + * + * @param paramStr + * @return + */ private static Map
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 5, 2014 2756 bclement Initial creation + * + *+ * + * @author bclement + * @version 1.0 + */ +public class Config{ + + public static final String HOST_KEY = "host"; + + public static final String PORT_KEY = "port"; + + public static final int PORT_DEFAULT = 9682; + + public static final String DATAPATH_KEY = "datapath"; + + public static final String DATAPATH_DEFAULT = "/session_data/"; + + public static final String LOGDIR_KEY = "logdir"; + + public static final String LOGDIR_DEFAULT = "logs"; + + public static final String LOGNAME_KEY = "logname"; + + public static final String LOGNAME_DEFAULT = "serverlog_yyyy_mm_dd.log"; + + public static final String STOREDIR_KEY = "storedir"; + + public static final String STOREDIR_DEFAULT = "store"; + + public static final String LEGACY_MODE_KEY = "legacy.mode"; + + public static final boolean LEGACY_MODE_DEFAULT = true; + + public static final String XMPP_USERNAME_KEY = "xmpp.username"; + + public static final String XMPP_PASSWORD_KEY = "xmpp.password"; + + public static final String XMPP_SERVER_KEY = "xmpp.server"; + + public static final String XMPP_SERVER_DEFAULT = "localhost"; + + public static final String config = System.getProperty( + "collaboration.dataserver.config", "config/settings.properties"); + + public static final String credentialsFile = System.getProperty( + "collaboration.dataserver.credentials", + "config/credentials.properties"); + + public static final Boolean useStdOut = Boolean + .getBoolean("collaboration.dataserver.stdout"); + + private static Properties _props = null; + + private static Properties _credProps = null; + + private Config() { + } + + /** + * Get cached properties. Loads if not initialized. + * + * @return + */ + private static synchronized Properties getProperties() { + if (_props == null) { + _props = new Properties(); + loadProperties(_props, config, false); + } + + return _props; + } + + /** + * Get cached credentials properties. Loads if not initialized. + * + * @return + */ + private static synchronized Properties getCredProperties() + throws RuntimeException { + if (_credProps == null) { + _credProps = new Properties(); + loadProperties(_credProps, credentialsFile, true); + } + + return _credProps; + } + + /** + * Loads properties from file system. If fatal is true, runtime exception is + * thrown on error. Otherwise, an error message is logged and defaults are + * used. + * + * @param props + * @param propertyFile + * @param fatal + */ + private static void loadProperties(Properties props, String propertyFile, + boolean fatal) throws RuntimeException { + try { + props.load(new FileInputStream(new File(propertyFile))); + } catch (Exception e) { + System.err.println("Unable to open properties file: " + + propertyFile + ". " + e.getLocalizedMessage()); + if (fatal) { + throw new RuntimeException( + "Unable to continue without configuration: " + + propertyFile, e); + } else { + e.printStackTrace(); + System.err.println("Continuing using defaults"); + } + } + } + + /** + * Get integer value from properties + * + * @param key + * @param defaultValue + * @return + */ + public static int getInt(String key, int defaultValue) { + Properties props = getProperties(); + String value = props.getProperty(key); + if (value == null) { + return defaultValue; + } else { + return Integer.parseInt(value); + } + } + + /** + * Get string value from properties + * + * @param key + * @param defaultValue + * @return + */ + public static String getProp(String key, String defaultValue) { + return getProperties().getProperty(key, defaultValue); + } + + /** + * Get boolean value from properties + * + * @param key + * @param defaultValue + * @return + */ + public static boolean getBool(String key, boolean defaultValue) { + Properties props = getProperties(); + String value = props.getProperty(key); + if (value == null) { + return defaultValue; + } else { + return Boolean.parseBoolean(value); + } + } + + /** + * @return username for XMPP account + * @throws RuntimeException + * if configuration for username cannot be found + */ + public static String getXmppUsername() throws RuntimeException { + return getRequiredCredential(XMPP_USERNAME_KEY); + } + + /** + * @return password for XMPP account + * @throws RuntimeException + * if configuration for password cannot be found + */ + public static String getXmppPassword() throws RuntimeException { + return getRequiredCredential(XMPP_PASSWORD_KEY); + } + + /** + * Get property that represents a web service path. Ensures a slash begins + * and ends the path. + * + * @param key + * @param defaultValue + * @return + */ + public static String getPath(String key, String defaultValue) { + String path = getProp(key, defaultValue).trim(); + if (!path.startsWith("/")) { + path = "/" + path; + } + if (!path.endsWith("/")) { + path = path + "/"; + } + return path; + } + + /** + * Get property from credentials file + * + * @param key + * @return + * @throws RuntimeException + * if credential configuration cannot be found + */ + private static String getRequiredCredential(String key) + throws RuntimeException { + Properties credProperties = getCredProperties(); + String rval = credProperties.getProperty(key); + if (rval == null) { + throw new RuntimeException( + "Missing required credentials property: " + key); + } + return rval; + } + + /** + * Get URL for data service. If host portion of URL is not found in config, + * this method will attempt to determine the canonical hostname for the + * machine + * + * @return + * @throws UnknownHostException + */ + public static String getDataserverUrl() throws UnknownHostException { + Properties props = getProperties(); + String host = props.getProperty(HOST_KEY); + if (host == null) { + host = InetAddress.getLocalHost().getCanonicalHostName(); + } + int port = getInt(PORT_KEY, PORT_DEFAULT); + String datapath = getPath(DATAPATH_KEY, DATAPATH_DEFAULT); + return "http://" + host + ":" + port + datapath; + } + +} diff --git a/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/DataService.java b/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/DataService.java new file mode 100644 index 0000000000..bacebcca64 --- /dev/null +++ b/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/DataService.java @@ -0,0 +1,236 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.collaboration.dataserver; + +import java.io.File; +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +import com.raytheon.uf.common.http.AcceptHeaderParser; +import com.raytheon.uf.common.http.AcceptHeaderValue; + +/** + * Servlet for storing and retrieving collaboration data objects + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 5, 2014 2756 bclement Initial creation + * + *+ * + * @author bclement + * @version 1.0 + */ +public class DataService extends HttpServlet { + + private static final long serialVersionUID = 3828421078339628468L; + + private final File base; + + private final FileManager manager; + + private final Logger log = Log.getLogger(this.getClass()); + + public static final String XML_CONTENT_TYPE = "text/xml"; + + public static final String HTML_CONTENT_TYPE = "text/html"; + + public static final String BINARY_CONTENT_TYPE = "application/octet-stream"; + + public static final String ACCEPT_HEADER = "accept"; + + private final boolean legacyMode; + + /** + * @param base + * base storage directory + */ + public DataService(File base) { + this.base = base; + if (!base.exists()) { + if (!base.mkdirs()) { + throw new IllegalStateException( + "Unable to create storage base directory: " + + base.getAbsolutePath()); + } + } + this.manager = new FileManager(base); + this.legacyMode = Config.getBool(Config.LEGACY_MODE_KEY, + Config.LEGACY_MODE_DEFAULT); + } + + /** + * + */ + public DataService() { + this(new File(Config.getProp(Config.STOREDIR_KEY, + Config.STOREDIR_DEFAULT))); + } + + /* + * (non-Javadoc) + * + * @see + * javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest + * , javax.servlet.http.HttpServletResponse) + */ + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + try { + File file = getFile(req); + if (!file.exists()) { + throw new RestException(HttpServletResponse.SC_NOT_FOUND, + "No Such Resource: " + file.getAbsolutePath()); + } + ServletOutputStream out = resp.getOutputStream(); + if (file.isDirectory()) { + if (acceptsXml(req)) { + resp.setContentType(XML_CONTENT_TYPE); + manager.readDirectoryAsXml(file, out); + } else { + resp.setContentType(HTML_CONTENT_TYPE); + manager.readDirectoryAsHtml(file, out); + } + } else { + resp.setContentType(BINARY_CONTENT_TYPE); + manager.readFile(file, out); + } + } catch (IOException e) { + log.warn("Problem handling GET", e); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } catch (RestException e) { + log.debug(e.getLocalizedMessage(), e); + resp.sendError(e.getCode()); + } + } + + /** + * @param req + * @return true if request has an accepts header that lists xml content type + */ + private boolean acceptsXml(HttpServletRequest req) { + String header = req.getHeader(ACCEPT_HEADER); + if (header == null || header.trim().isEmpty()) { + return false; + } + for (AcceptHeaderValue value : new AcceptHeaderParser(header)) { + String type = value.getEncoding(); + if (type.equalsIgnoreCase(XML_CONTENT_TYPE) && value.isAcceptable()) { + return true; + } + } + return false; + } + + /* + * (non-Javadoc) + * + * @see + * javax.servlet.http.HttpServlet#doPut(javax.servlet.http.HttpServletRequest + * , javax.servlet.http.HttpServletResponse) + */ + @Override + protected void doPut(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + // TODO auth + try { + File file = getFile(req); + manager.writeFile(req.getInputStream(), file); + } catch (IOException e) { + log.warn("Problem handling PUT", e); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } catch (RestException e) { + log.debug(e.getLocalizedMessage(), e); + resp.sendError(e.getCode()); + } + } + + /** + * Create file object from request path + * + * @param req + * @return + */ + private File getFile(HttpServletRequest req) { + String pathInfo = req.getPathInfo(); + return new File(base, pathInfo); + } + + /* + * (non-Javadoc) + * + * @see + * javax.servlet.http.HttpServlet#doDelete(javax.servlet.http.HttpServletRequest + * , javax.servlet.http.HttpServletResponse) + */ + @Override + protected void doDelete(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + // TODO auth + try { + File file = getFile(req); + if (!file.exists()) { + throw new RestException(HttpServletResponse.SC_NOT_FOUND, + "No Such Resource: " + file.getAbsolutePath()); + } + manager.delete(file); + } catch (IOException e) { + log.warn("Problem handling DELETE", e); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } catch (RestException e) { + log.debug(e.getLocalizedMessage(), e); + resp.sendError(e.getCode()); + } + } + + /* + * (non-Javadoc) + * + * @see + * javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest + * , javax.servlet.http.HttpServletResponse) + */ + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + String method = req.getMethod(); + // clients before 14.3 used DAV which uses MKCOL. This isn't needed + // since we create directories on put. + if (legacyMode && "MKCOL".equalsIgnoreCase(method)) { + resp.setStatus(HttpServletResponse.SC_OK); + return; + } + super.service(req, resp); + } + +} diff --git a/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/DataserverMain.java b/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/DataserverMain.java new file mode 100644 index 0000000000..41268f2fbc --- /dev/null +++ b/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/DataserverMain.java @@ -0,0 +1,129 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.collaboration.dataserver; + +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.util.TimeZone; + +import org.eclipse.jetty.util.RolloverFileOutputStream; + +/** + * Entry class for dataserver + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 5, 2014 2756 bclement Initial creation + * + *+ * + * @author bclement + * @version 1.0 + */ +public class DataserverMain { + + private static final int CONNECTION_DELAY = 10000; // 10 seconds + + private static final int SHUTDOWN_DELAY = 1000; // 1 second + + /** + * @param args + * @throws IOException + */ + public static void main(String[] args) throws IOException { + try { + configureLogging(); + } catch (IOException e) { + System.err.println("Unable to configure logging: " + + e.getLocalizedMessage()); + System.err + .println("Continuing using standard out and standard error"); + } + final XmppServerConnection xmppConnection; + try { + xmppConnection = new XmppServerConnection(); + } catch (Exception e) { + System.err + .println("Unable to connect to XMPP server, shutting down"); + e.printStackTrace(); + return; + } + final WebServerRunner webServer = new WebServerRunner(); + new Thread(webServer).start(); + wait(CONNECTION_DELAY); + new Thread(xmppConnection).start(); + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + System.out.println("Server shutting down"); + xmppConnection.disconnect(); + webServer.stop(); + DataserverMain.wait(SHUTDOWN_DELAY); + } + }); + } + + /** + * sleep thread for specified milliseconds + * + * @param millis + */ + private static void wait(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * Set up rolling file log unless standard out is to be used + * + * @throws IOException + */ + private static void configureLogging() throws IOException { + if (Config.useStdOut){ + return; + } + File logDir = new File(Config.getProp(Config.LOGDIR_KEY, Config.LOGDIR_DEFAULT)); + if ( !logDir.exists()){ + if (!logDir.mkdirs()) { + throw new IOException( + "Unable to create configured logging directory: " + + logDir.getAbsolutePath()); + } + } else if (!logDir.isDirectory()){ + throw new IOException( + "Configured logging directory exists but is not a directory: " + + logDir.getAbsolutePath()); + } + String logFileName = logDir.getAbsolutePath() + File.separator + + Config.getProp(Config.LOGNAME_KEY, Config.LOGNAME_DEFAULT); + RolloverFileOutputStream out = new RolloverFileOutputStream( + logFileName, true, 0, TimeZone.getTimeZone("GMT")); + System.setErr(new PrintStream(out)); + System.setOut(new PrintStream(out)); + } + +} diff --git a/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/FileManager.java b/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/FileManager.java new file mode 100644 index 0000000000..9e7387b5a4 --- /dev/null +++ b/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/FileManager.java @@ -0,0 +1,443 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.collaboration.dataserver; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import javax.servlet.http.HttpServletResponse; + +import com.raytheon.uf.common.util.concurrent.KeyLock; +import com.raytheon.uf.common.util.concurrent.KeyLocker; + +/** + * Collaboration event object data storage that uses the file system. Uses a + * read/write lock policy based on file path. The paths are locked from the base + * to the target node and unlocked in reverse order. + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 6, 2014 2756 bclement Initial creation + * + *+ * + * @author bclement + * @version 1.0 + */ +public class FileManager { + + private static final int BUFFER_SIZE = 1024 * 256; // 256K + + private static final ThreadLocal
* @@ -31,33 +28,35 @@ import java.io.File; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Aug 07, 2012 bkowal Initial creation - * Jan 06, 2013 2563 bclement removed config preamble + * Feb 6, 2014 2756 bclement Initial creation * ** - * @author bkowal + * @author bclement * @version 1.0 */ +public class RestException extends Exception{ -public abstract class HttpdCollaborationUtil { - - public static String encodeErrorMessage(Throwable e) { - String content = e.getMessage(); - if (content == null) { - // final attempt - content = e.toString(); - } - - return "error : " + content; - } - - public static String endPathIfNecessary(String _path) { - if (_path.endsWith(File.separator)) { - return _path; - } - - return _path + File.separator; + private static final long serialVersionUID = -3940227418233750698L; + + private final int code; + + + /** + * @param code + * http status code + * @param message + */ + public RestException(int code, String message) { + super(message); + this.code = code; } -} \ No newline at end of file + /** + * @return the code + */ + public int getCode() { + return code; + } + +} diff --git a/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/WebServerRunner.java b/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/WebServerRunner.java new file mode 100644 index 0000000000..08f251d796 --- /dev/null +++ b/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/WebServerRunner.java @@ -0,0 +1,93 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.collaboration.dataserver; + +import java.io.File; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; + +/** + * Start and run jetty webserver + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 14, 2014 2756 bclement Initial creation + * + *+ * + * @author bclement + * @version 1.0 + */ +public class WebServerRunner implements Runnable { + + private Server server; + + /* (non-Javadoc) + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + server = new Server(Config.getInt(Config.PORT_KEY, + Config.PORT_DEFAULT)); + + ServletContextHandler context = new ServletContextHandler( + ServletContextHandler.SESSIONS); + context.setContextPath("/"); + server.setHandler(context); + + File base = new File(Config.getProp(Config.STOREDIR_KEY, + Config.STOREDIR_DEFAULT)); + if (!base.exists()) { + base.mkdirs(); + } + + String datapath = Config.getPath(Config.DATAPATH_KEY, + Config.DATAPATH_DEFAULT); + context.addServlet(new ServletHolder(new DataService(base)), datapath + + "*"); + try { + server.start(); + System.out.println("Server started"); + server.join(); + } catch (Exception e) { + System.err.println("Unable to start web server"); + e.printStackTrace(); + } + } + + /** + * Shutdown web server + */ + public void stop() { + try { + server.stop(); + } catch (Exception e) { + System.err.println("Unable to stop web server"); + e.printStackTrace(); + } + } + +} diff --git a/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/XmppServerConnection.java b/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/XmppServerConnection.java new file mode 100644 index 0000000000..42413b23a6 --- /dev/null +++ b/javaUtilities/collaboration.dataserver/src/com/raytheon/collaboration/dataserver/XmppServerConnection.java @@ -0,0 +1,135 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.collaboration.dataserver; + +import java.net.UnknownHostException; + +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.jivesoftware.smack.PacketListener; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.filter.PacketFilter; +import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.IQ.Type; +import org.jivesoftware.smack.packet.Packet; +import org.jivesoftware.smack.util.SyncPacketSend; + +/** + * Starts and runs XMPP client thread for communication with XMPP server + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 14, 2014 2756 bclement Initial creation + * + *+ * + * @author bclement + * @version 1.0 + */ +public class XmppServerConnection implements Runnable { + + private static final int PACKET_SEND_TIMEOUT = 5000; // 5 seconds + + private final XMPPConnection conn; + + private final String user; + + private final String password; + + private final String xmppServerAddress; + + private final String dataServerUrl; + + private final Logger log = Log.getLogger(this.getClass()); + + /** + * Creates connection and logs in + * + * @throws XMPPException + * @throws UnknownHostException + */ + public XmppServerConnection() throws XMPPException, UnknownHostException { + this.dataServerUrl = Config.getDataserverUrl(); + this.user = Config.getXmppUsername(); + this.password = Config.getXmppPassword(); + this.xmppServerAddress = Config.getProp(Config.XMPP_SERVER_KEY, + Config.XMPP_SERVER_DEFAULT); + this.conn = new XMPPConnection(xmppServerAddress); + this.conn.connect(); + this.conn.login(user, password); + log.debug("Connected to XMPP server at address: " + xmppServerAddress); + } + + /* (non-Javadoc) + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + conn.addPacketListener(new PacketListener() { + @Override + public void processPacket(Packet packet) { + log.debug(packet.toXML()); + } + }, new PacketFilter() { + @Override + public boolean accept(Packet packet) { + return true; + } + }); + IQ packet = new IQ() { + @Override + public String getChildElementXML() { + return "
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Aug 07, 2012 bkowal Initial creation + * Jan 06, 2013 2563 bclement replaced TaskEngine shutdown with cancel task + * added legacy format setter/accessor + * Feb 14, 2013 2756 bclement rename and refactor for operation with generic http + * server configured over XMPP + * + *+ * + * @author bkowal + * @version 1.0 + */ +public class HttpConfigurationPlugin implements Plugin { + private static final Logger logger = LoggerFactory + .getLogger(HttpConfigurationPlugin.class); + + private static final String INTERVAL = "plugin.collaboration.http.interval"; + + private static final long DEFAULT_INTERVAL_MS = 60000; + + private static final long MONITOR_DELAY_MS = 10000; /* 10 seconds */ + + private TaskEngine monitorTaskEngine; + + private CollaborationSessionEventListener listener; + + private HttpStatusMonitor httpStatusMonitor; + + /** + * + */ + public HttpConfigurationPlugin() { + } + + /* + * (non-Javadoc) + * + * @see org.jivesoftware.openfire.container.Plugin#destroyPlugin() + */ + @Override + public void destroyPlugin() { + if ((this.listener == null) == false) { + SessionEventDispatcher.removeListener(this.listener); + + this.listener.dispose(); + this.listener = null; + } + + if ((this.monitorTaskEngine == null) == false) { + // we don't want to shutdown the engine since it is a singleton + // if we do, we can't reload the plugin + this.monitorTaskEngine + .cancelScheduledTask(this.httpStatusMonitor); + this.monitorTaskEngine = null; + } + } + + /** + * Registers IQ configuration handlers with IQ router and adds features to + * info discovery + * + * @param server + * @param handlers + */ + private void registerConfigHandlers(XMPPServer server, + List
- * - * SOFTWARE HISTORY - * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Aug 07, 2012 bkowal Initial creation - * Jan 06, 2013 2563 bclement replaced TaskEngine shutdown with cancel task - * added legacy format setter/accessor - * - *- * - * @author bkowal - * @version 1.0 - */ -public class HttpdCollaborationConfigurationPlugin implements Plugin { - private static final Logger logger = LoggerFactory - .getLogger(HttpdCollaborationConfigurationPlugin.class); - - private static final String LOCATION = "plugin.collaboration.httpd.location"; - - private static final String INTERVAL = "plugin.collaboration.httpd.interval"; - - private static final String DEFAULT_LOCATION = "/awips2/httpd_collaboration"; - - private static final long DEFAULT_INTERVAL_MS = 60000; - - private static final long MONITOR_DELAY_MS = 60000; /* 1 Minute */ - - private static final String ABORT_ERROR_MESSAGE = "Aborting initialization of the HttpdCollaborationConfigurationPlugin plugin."; - - private HttpdCollaborationSessionEventListener listener; - - private HttpdCollaborationStatusMonitor httpdCollaborationStatusMonitor; - - private TaskEngine monitorTaskEngine; - - /** - * - */ - public HttpdCollaborationConfigurationPlugin() { - } - - /* - * (non-Javadoc) - * - * @see org.jivesoftware.openfire.container.Plugin#destroyPlugin() - */ - @Override - public void destroyPlugin() { - if ((this.listener == null) == false) { - SessionEventDispatcher.removeListener(this.listener); - - this.listener.dispose(); - this.listener = null; - } - - if ((this.monitorTaskEngine == null) == false) { - // we don't want to shutdown the engine since it is a singleton - // if we do, we can't reload the plugin - this.monitorTaskEngine - .cancelScheduledTask(this.httpdCollaborationStatusMonitor); - this.monitorTaskEngine = null; - } - } - - /* - * (non-Javadoc) - * - * @see - * org.jivesoftware.openfire.container.Plugin#initializePlugin(org.jivesoftware - * .openfire.container.PluginManager, java.io.File) - */ - @Override - public void initializePlugin(PluginManager arg0, File arg1) { - /* - * Attempt to read the httpd collaboration configuration. - */ - HttpdCollaborationConfReader confReader = new HttpdCollaborationConfReader( - this.getHttpdCollaborationLocation()); - try { - confReader.execute(); - } catch (ConfigurationException e1) { - logger.error("Unable to read the httpd collaboration configuration.", - e1); - logger.error(ABORT_ERROR_MESSAGE); - return; - } catch (Exception e2) { - logger.error("An unexpected error has occurred.", e2); - logger.error(ABORT_ERROR_MESSAGE); - return; - } - - /* - * Determine the hostname - there is a requirement in place that - * requires openfire and httpd-collaboration to be installed on the same - * machine. - */ - InetAddress address = null; - try { - address = InetAddress.getLocalHost(); - } catch (UnknownHostException e1) { - logger.error("Unable to retrieve the hostname.", e1); - logger.error(ABORT_ERROR_MESSAGE); - return; - } - - /* Persist the configuration information. */ - HttpdCollaborationConfiguration httpdCollaborationConfiguration = new HttpdCollaborationConfiguration(); - httpdCollaborationConfiguration.setSessionDataHost(address - .getHostName()); - httpdCollaborationConfiguration.setSessionDataPort(confReader - .getListenPort()); - - /* The httpd-collaboration status monitor */ - this.httpdCollaborationStatusMonitor = new HttpdCollaborationStatusMonitor( - this.getHttpdCollaborationLocation(), - httpdCollaborationConfiguration.getHttpdCollaborationURL(), - httpdCollaborationConfiguration.toString()); - - /* Retrieve openfire components. */ - JID serverAddress = new JID(XMPPServer.getInstance().getServerInfo() - .getXMPPDomain()); - MessageRouter router = XMPPServer.getInstance().getMessageRouter(); - - /* Create a new listener. */ - this.listener = new HttpdCollaborationSessionEventListener( - httpdCollaborationConfiguration.toString()); - - /* Initialize the listener. */ - this.listener - .setHttpdCollaborationStatusChecker(this.httpdCollaborationStatusMonitor); - this.listener.setServerAddress(serverAddress); - this.listener.setRouter(router); - - /* Make it possible for the listener to receive events. */ - SessionEventDispatcher.addListener(this.listener); - this.scheduleStatusMonitor(); - } - - /** - * Schedules the httpd collaboration status monitor at the specified, - * configurable interval using the openfire TaskEngine; see - * {@link TaskEngine} - */ - private synchronized void scheduleStatusMonitor() { - logger.info("Scheduling the httpd collaboration status monitor ..."); - if (this.monitorTaskEngine == null) { - this.monitorTaskEngine = TaskEngine.getInstance(); - } - this.monitorTaskEngine.schedule(this.httpdCollaborationStatusMonitor, - MONITOR_DELAY_MS, this.getHttpdMonitorInterval()); - } - - /** - * Stops the scheduled httpd collaboration status monitor if it has been - * scheduled. - */ - private synchronized void stopStatusMonitor() { - if (this.monitorTaskEngine == null) { - return; - } - this.monitorTaskEngine - .cancelScheduledTask(this.httpdCollaborationStatusMonitor); - } - - /** - * Sets the configurable installation location of awips2-httpd-collaboration - * - * @param _location - * the location of awips2-httpd-collaboration - */ - public void setHttpdCollaborationLocation(String _location) { - JiveGlobals.setProperty(LOCATION, _location); - } - - /** - * Returns the installation location of awips2-httpd-collaboration from the - * openfire configuration - * - * @return the installation root of awips2-httpd-collaboration - */ - public String getHttpdCollaborationLocation() { - return JiveGlobals.getProperty(LOCATION, DEFAULT_LOCATION); - } - - /** - * Sets the configurable interval for the amount of time between executions - * of the httpd collaboration status monitor - * - * @param _interval - * the interval in milliseconds - */ - public void setHttpdMonitorInterval(long _interval) { - long originalInterval = this.getHttpdMonitorInterval(); - if (_interval == originalInterval) { - return; - } - JiveGlobals.setProperty(INTERVAL, Long.toString(_interval)); - this.stopStatusMonitor(); - this.scheduleStatusMonitor(); - } - - /** - * Returns the interval from the openfire configuration - * - * @return the interval in milliseconds - */ - public long getHttpdMonitorInterval() { - return JiveGlobals.getLongProperty(INTERVAL, DEFAULT_INTERVAL_MS); - } - - /** - * Sets the global value for toggling pre 14.3 message format support - * - * @param legacy - */ - public void setLegacySupport(boolean legacy) { - JiveGlobals.setProperty(ConfigurationPacket.LEGACY_KEY, - Boolean.toString(legacy)); - } - - /** - * @return true if configured to support pre 14.3 message format - */ - public boolean hasLegacySupport() { - return JiveGlobals.getBooleanProperty(ConfigurationPacket.LEGACY_KEY, - true); - } - -} \ No newline at end of file diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/configuration/ConfigurationPacket.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/configuration/ConfigurationPacket.java index ca332ecc6c..02ffdc0570 100644 --- a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/configuration/ConfigurationPacket.java +++ b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/configuration/ConfigurationPacket.java @@ -19,11 +19,6 @@ **/ package com.raytheon.openfire.plugin.configuration.collaboration.configuration; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Properties; - import org.apache.commons.lang.StringUtils; import org.dom4j.Element; import org.jivesoftware.util.JiveGlobals; @@ -32,6 +27,7 @@ import org.slf4j.LoggerFactory; import org.xmpp.packet.Message; import org.xmpp.packet.PacketExtension; + /** * Packet extension for collaboration configuration messages to clients * @@ -42,6 +38,7 @@ import org.xmpp.packet.PacketExtension; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Dec 20, 2013 bclement Initial creation + * Feb 14, 2014 2756 bclement moved preferences to separate file * * * @@ -54,33 +51,6 @@ public class ConfigurationPacket extends PacketExtension { private static final Logger log = LoggerFactory .getLogger(ConfigurationPacket.class); - // format property file - - public static final String CONFIG_FILE_KEY = "plugin.collaboration.packet.format.file"; - - private static final String DEFAULT_PLUGIN_CONFIG_FILE = "conf" - + File.separator + "configurationPacketFormat.properties"; - - private static final Properties properties = new Properties(); - - static { - String confFile = JiveGlobals.getProperty(CONFIG_FILE_KEY, - DEFAULT_PLUGIN_CONFIG_FILE); - File f = new File(JiveGlobals.getHomeDirectory(), confFile); - if (f.exists()) { - try { - properties.load(new FileInputStream(f)); - } catch (IOException e) { - // defaults will be used - log.error("Problem loading packet format configuration file: " - + f.getAbsolutePath(), e); - } - } else { - log.info("Using default config packet format since there was no format file at " - + f.getAbsolutePath()); - } - } - // property keys public static final String XMLNS_KEY = "plugin.collaboration.packet.xmlns"; @@ -128,11 +98,11 @@ public class ConfigurationPacket extends PacketExtension { * configuration payload for packet * @return */ - private static Element create(String body) { - String element = properties.getProperty(ELEMENT_KEY, ELEMENT_DEFAULT); - String xmlns = properties.getProperty(XMLNS_KEY, XMLNS_DEFAULT); + public static Element create(String body) { + String element = PacketPreferences.get(ELEMENT_KEY, ELEMENT_DEFAULT); + String xmlns = PacketPreferences.get(XMLNS_KEY, XMLNS_DEFAULT); Element rval = docFactory.createElement(element, xmlns); - String attributes = properties.getProperty(ATTRIBUTES_KEY, + String attributes = PacketPreferences.get(ATTRIBUTES_KEY, ATTRIBUTES_DEFAULT); for (String keyval : StringUtils.split(attributes, ',')) { String[] separated = StringUtils.split(keyval, '='); diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/configuration/HttpdCollaborationConfiguration.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/configuration/HttpdCollaborationConfiguration.java deleted file mode 100644 index c1da2f4682..0000000000 --- a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/configuration/HttpdCollaborationConfiguration.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.openfire.plugin.configuration.collaboration.configuration; - - -/** - * Used to store and format the information retrieved from the - * httpd-collaboration httpd.conf file that will be returned to the client. - * - *
- * - * SOFTWARE HISTORY - * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Aug 07, 2012 bkowal Initial creation - * Jan 06, 2013 2563 bclement removed config preamble - * - *- * - * @author bkowal - * @version 1.0 - */ -public class HttpdCollaborationConfiguration { - private static final String SESSION_DATA_URL_FORMAT_STRING = "http://%s:%s/session_data/"; - - private static final String URL_PARAMETER_NAME = "sessionDataHttpURL"; - - private String sessionDataHost; - - private String sessionDataPort; - - /** - * - */ - public HttpdCollaborationConfiguration() { - this.sessionDataHost = null; - this.sessionDataPort = null; - } - - @Override - public String toString() { - return URL_PARAMETER_NAME + " : " + this.getHttpdCollaborationURL(); - } - - public String getHttpdCollaborationURL() { - return String.format(SESSION_DATA_URL_FORMAT_STRING, - this.sessionDataHost, this.sessionDataPort); - } - - public String getSessionDataHost() { - return sessionDataHost; - } - - public void setSessionDataHost(String sessionDataHost) { - this.sessionDataHost = sessionDataHost; - } - - public String getSessionDataPort() { - return sessionDataPort; - } - - public void setSessionDataPort(String sessionDataPort) { - this.sessionDataPort = sessionDataPort; - } -} \ No newline at end of file diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/configuration/PacketPreferences.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/configuration/PacketPreferences.java new file mode 100644 index 0000000000..f738b1b6ea --- /dev/null +++ b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/configuration/PacketPreferences.java @@ -0,0 +1,91 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.openfire.plugin.configuration.collaboration.configuration; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; + +import org.jivesoftware.util.JiveGlobals; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Preferences wrapper for packet format + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 10, 2014 2756 bclement Initial creation + * + *+ * + * @author bclement + * @version 1.0 + */ +public class PacketPreferences { + + private static final Logger log = LoggerFactory + .getLogger(PacketPreferences.class); + + // format property file + + public static final String CONFIG_FILE_KEY = "plugin.collaboration.packet.format.file"; + + private static final String DEFAULT_PLUGIN_CONFIG_FILE = "conf" + + File.separator + "configurationPacketFormat.properties"; + + private static final Properties properties = new Properties(); + + static { + String confFile = JiveGlobals.getProperty(CONFIG_FILE_KEY, + DEFAULT_PLUGIN_CONFIG_FILE); + File f = new File(JiveGlobals.getHomeDirectory(), confFile); + if (f.exists()) { + try { + properties.load(new FileInputStream(f)); + } catch (IOException e) { + // defaults will be used + log.error("Problem loading packet format configuration file: " + + f.getAbsolutePath(), e); + } + } else { + log.info("Using default config packet format since there was no format file at " + + f.getAbsolutePath()); + } + } + + /** + * Get property from configuration file. Returns defaultValue if key doesn't + * exist + * + * @param key + * @param defaultValue + * @return + */ + public static String get(String key, String defaultValue) { + return properties.getProperty(key, defaultValue); + } + +} diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/exception/HttpdCollaborationNotRunningException.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/exception/HttpdCollaborationNotRunningException.java deleted file mode 100644 index f590a498ad..0000000000 --- a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/exception/HttpdCollaborationNotRunningException.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.openfire.plugin.configuration.collaboration.exception; - -/** - * Implements an exception that is thrown whenever one of the conditions - * indicating httpd-collaboration is not running occurs. - * - *
- * - * SOFTWARE HISTORY - * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Jul 30, 2012 bkowal Initial creation - * - *- * - * @author bkowal - * @version 1.0 - */ - -public class HttpdCollaborationNotRunningException extends Throwable { - - private static final long serialVersionUID = 6598229436212894638L; - private static final String MESSAGE_PREFIX = "The httpd-collaboration server is not running; "; - - /** - * - */ - public HttpdCollaborationNotRunningException() { - } - - /** - * @param message - */ - public HttpdCollaborationNotRunningException(String message) { - super(MESSAGE_PREFIX + message); - } - - /** - * @param cause - */ - public HttpdCollaborationNotRunningException(Throwable cause) { - super(cause); - } - - /** - * @param message - * @param cause - */ - public HttpdCollaborationNotRunningException(String message, Throwable cause) { - super(MESSAGE_PREFIX + message, cause); - } - -} diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/exception/HttpdCollaborationStatusException.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/exception/HttpdCollaborationStatusException.java deleted file mode 100644 index 1e947118d9..0000000000 --- a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/exception/HttpdCollaborationStatusException.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.openfire.plugin.configuration.collaboration.exception; - -/** - * Implements an exception that is thrown whenever it is not possible to - * determine whether or not httpd-collaboration is currently running. - * - *
- * - * SOFTWARE HISTORY - * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Jul 30, 2012 bkowal Initial creation - * - *- * - * @author bkowal - * @version 1.0 - */ - -public class HttpdCollaborationStatusException extends Throwable { - - private static final long serialVersionUID = -2446532142660776343L; - private static final String MESSAGE_PREFIX = "Unable to determine the status of the httpd-collaboration server; "; - - /** - * - */ - public HttpdCollaborationStatusException() { - // TODO Auto-generated constructor stub - } - - /** - * @param message - */ - public HttpdCollaborationStatusException(String message) { - super(MESSAGE_PREFIX + message); - } - - /** - * @param cause - */ - public HttpdCollaborationStatusException(Throwable cause) { - super(cause); - } - - /** - * @param message - * @param cause - */ - public HttpdCollaborationStatusException(String message, Throwable cause) { - super(MESSAGE_PREFIX + message, cause); - } - -} diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/http/HttpStatusMonitor.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/http/HttpStatusMonitor.java new file mode 100644 index 0000000000..7aa32622a3 --- /dev/null +++ b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/http/HttpStatusMonitor.java @@ -0,0 +1,259 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.openfire.plugin.configuration.collaboration.http; + +import java.io.IOException; +import java.util.TimerTask; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.http.HttpStatus; +import org.jivesoftware.openfire.SessionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xmpp.packet.JID; +import org.xmpp.packet.Message; + +import com.raytheon.openfire.plugin.configuration.collaboration.configuration.ConfigurationPacket; +import com.raytheon.openfire.plugin.configuration.collaboration.iq.AbstractConfigHandler; +import com.raytheon.openfire.plugin.configuration.collaboration.iq.HttpAddressHandler; + +/** + * Runs a series of checks to determine if http collaboration is still running + * on-demand and on a scheduled basis. The checks include: verifying that a url + * is configured for the primary dataserver and executing an http GET request + * against the http dataserver. + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Jul 26, 2012 bkowal Initial creation + * Jan 06, 2013 2563 bclement replaced chat message with packet extension + * Feb 14, 2013 2756 bclement rename and refactor for operation with generic http + * server configured over XMPP + * + *+ * + * @author bkowal + * @version 1.0 + */ + +public class HttpStatusMonitor extends TimerTask { + private static final Logger logger = LoggerFactory + .getLogger(HttpStatusMonitor.class); + + private final SessionManager sessionManager; + + private static final HttpClient httpClient = new HttpClient(); + + private GetMethod _getMethod = null; + + private String _previousUrl = null; + + private static enum Status { + URL_UNSET, SERVER_DOWN, SERVER_UP + } + + private Status status = Status.URL_UNSET; + + private final HttpAddressHandler addressHandler; + + private final JID serverId; + + /** + * @param addressHandler + * IQ hander responsible for http url configuration + * @param serverId + * id of server used as from address in messages + */ + public HttpStatusMonitor(HttpAddressHandler addressHandler, JID serverId) { + this.sessionManager = SessionManager.getInstance(); + this.addressHandler = addressHandler; + this.serverId = serverId; + } + + /** + * Get the current URL configuration string. + * + * @return null if no valid configuration is available + */ + public String getCurrentUrlConfig() { + String primary = AbstractConfigHandler.getPrimaryDataServer(); + if (primary == null) { + logger.debug("No primary dataserver found"); + urlUnset(); + return null; + } else { + String url = addressHandler.getHttpAddress(primary); + if (url == null) { + logger.debug("No url set for dataserver: " + primary); + urlUnset(); + return null; + } else { + return verifyHttpProcess(url); + } + } + } + + /** + * Verify that the http server is online and accepting requests. Returns the + * valid URL configuration string. + * + * @param url + * url to verify + * @return null if successful request cannot be made + */ + private String verifyHttpProcess(String url) { + synchronized (httpClient) { + int statusCode = -1; + try { + GetMethod get = getCachedMethod(url); + statusCode = httpClient.executeMethod(get); + } catch (HttpException e1) { + String msg = "Unable to execute GET against the collaboration dataserver at " + + url; + logger.error(msg, e1); + setOffline(msg); + } catch (IOException e2) { + String msg = "Unable to read the response from the collaboration dataserver at " + + url; + logger.error(msg, e2); + setOffline(msg); + } + + if ((statusCode == HttpStatus.SC_OK) == false) { + String msg = "Dataserver not is not available - received status " + + statusCode; + logger.error(msg); + setOffline(msg); + return null; + } else { + String urlConfig = "sessionDataHttpURL : " + url; + setOnline(urlConfig); + return urlConfig; + } + } + } + + /** + * Get the http GET method for url. Uses a simple cache. + * + * @param url + * @return + */ + private GetMethod getCachedMethod(String url) { + if (_previousUrl == null || !_previousUrl.equals(url)) { + logger.debug("Dataserver url changed from " + _previousUrl + " to " + + url); + _getMethod = new GetMethod(url); + _previousUrl = url; + } + return _getMethod; + } + + @Override + public void run() { + logger.debug("Verifying that httpd-collaboration is still available ..."); + getCurrentUrlConfig(); + } + + /** + * Broadcast configuration message to all users + * + * @param body + * url or error configuration string + */ + private synchronized void broadcastMessage(String body) { + logger.debug("Broadcasting message: " + body); + Message message = ConfigurationPacket.createMessage(body); + message.setFrom(serverId); + this.sessionManager.broadcast(message); + } + + /** + * Method to call when http server cannot be reached + * + * @param message + */ + private void setOffline(String message) { + switch (status) { + case SERVER_UP: + logger.debug("Status changing from " + status + " to " + + Status.SERVER_DOWN); + broadcastMessage(formatError(message)); + status = Status.SERVER_DOWN; + default: + logger.debug("SetOffline: Status not changed from " + status); + // no action since we don't want to spam with error messages + break; + } + } + + /** + * Format error message to configuration format + * + * @param message + * @return + */ + private String formatError(String message) { + return "error : " + message; + } + + /** + * Method to call when http server is configured and running + * + * @param urlConfig + */ + private void setOnline(String urlConfig) { + switch (status) { + case SERVER_DOWN: + case URL_UNSET: + logger.debug("Status changing from " + status + " to " + + Status.SERVER_UP); + broadcastMessage(urlConfig); + status = Status.SERVER_UP; + break; + default: + logger.debug("SetOnline: Status not changed from " + status); + // no action + } + } + + /** + * Method to call when http server url is not configured + */ + private void urlUnset() { + switch (status) { + case SERVER_UP: + logger.debug("Status changing from " + status + " to " + + Status.URL_UNSET); + broadcastMessage(formatError("Dataserver does not have URL configured in chat server.")); + status = Status.URL_UNSET; + default: + logger.debug("UrlUnset: Status not changed from " + status); + // no action since we don't want to spam with error messages + break; + } + } +} \ No newline at end of file diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/httpd/HttpdCollaborationConfReader.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/httpd/HttpdCollaborationConfReader.java deleted file mode 100644 index 7a253b6c7b..0000000000 --- a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/httpd/HttpdCollaborationConfReader.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.openfire.plugin.configuration.collaboration.httpd; - -import org.apache.commons.configuration.ConfigurationException; - -import com.raytheon.openfire.plugin.configuration.collaboration.util.HttpdCollaborationUtil; - -/** - * Reads the httpd.conf file for the configurable httpd-collaboration instance. - * - *
- * - * SOFTWARE HISTORY - * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Aug 7, 2012 bkowal Initial creation - * - *- * - * @author bkowal - * @version 1.0 - */ -public class HttpdCollaborationConfReader { - private static String CONF_FILE; - - private static final String LISTEN_PROPERTY = "Listen"; - - private HttpdCollaborationPropertiesConfiguration propertiesConfiguration; - - /** - * - */ - public HttpdCollaborationConfReader(String _location) { - CONF_FILE = HttpdCollaborationUtil.endPathIfNecessary(_location) - + "etc/httpd/conf/httpd.conf"; - } - - public void execute() throws ConfigurationException { - this.propertiesConfiguration = new HttpdCollaborationPropertiesConfiguration(); - this.propertiesConfiguration.load(CONF_FILE); - } - - public String getListenPort() { - return this.propertiesConfiguration.getString(LISTEN_PROPERTY); - } -} \ No newline at end of file diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/httpd/HttpdCollaborationPropertiesConfiguration.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/httpd/HttpdCollaborationPropertiesConfiguration.java deleted file mode 100644 index 23afdecbfe..0000000000 --- a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/httpd/HttpdCollaborationPropertiesConfiguration.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.openfire.plugin.configuration.collaboration.httpd; - -import java.io.File; -import java.net.URL; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; - -/** - * This class was created because version 1.6 of commons configuration does not - * allow you to decide whether you want to allow includes or not. There is a - * 'setIncludesAllowed' method; however, it is protected. - * - *
- * - * SOFTWARE HISTORY - * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Aug 2012 bkowal Initial creation - * - *- * - * @author bkowal - * @version 1.0 - */ -public class HttpdCollaborationPropertiesConfiguration extends PropertiesConfiguration { - /** - * - */ - public HttpdCollaborationPropertiesConfiguration() { - super(); - } - - /** - * @param fileName - * @throws ConfigurationException - */ - public HttpdCollaborationPropertiesConfiguration(String fileName) - throws ConfigurationException { - super(fileName); - } - - /** - * @param file - * @throws ConfigurationException - */ - public HttpdCollaborationPropertiesConfiguration(File file) throws ConfigurationException { - super(file); - } - - /** - * @param url - * @throws ConfigurationException - */ - public HttpdCollaborationPropertiesConfiguration(URL url) throws ConfigurationException { - super(url); - } - - @Override - public void setBasePath(String basePath) { - super.setBasePath(basePath); - this.setIncludesAllowed(false); - } -} \ No newline at end of file diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/httpd/HttpdCollaborationStatusMonitor.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/httpd/HttpdCollaborationStatusMonitor.java deleted file mode 100644 index 54bd8681ac..0000000000 --- a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/httpd/HttpdCollaborationStatusMonitor.java +++ /dev/null @@ -1,180 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.openfire.plugin.configuration.collaboration.httpd; - -import java.io.File; -import java.io.IOException; -import java.util.TimerTask; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.http.HttpStatus; -import org.jivesoftware.openfire.SessionManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xmpp.packet.Message; - -import com.raytheon.openfire.plugin.configuration.collaboration.configuration.ConfigurationPacket; -import com.raytheon.openfire.plugin.configuration.collaboration.exception.HttpdCollaborationNotRunningException; -import com.raytheon.openfire.plugin.configuration.collaboration.exception.HttpdCollaborationStatusException; -import com.raytheon.openfire.plugin.configuration.collaboration.util.HttpdCollaborationUtil; - -/** - * Runs a series of checks to determine if httpd-collaboration is still running - * on-demand and on a scheduled basis. The checks include: verifying that a pid - * file exists for httpd-collaboration and executing an http GET request against - * the httpd-collaboration server. - * - *
- * - * SOFTWARE HISTORY - * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Jul 26, 2012 bkowal Initial creation - * Jan 06, 2013 2563 bclement replaced chat message with packet extension - * - *- * - * @author bkowal - * @version 1.0 - */ - -public class HttpdCollaborationStatusMonitor extends TimerTask { - private static final Logger logger = LoggerFactory - .getLogger(HttpdCollaborationStatusMonitor.class); - - private SessionManager sessionManager; - - private boolean httpdCollaborationBecameUnavailable; - - // provided by the configuration - private String HTTPD_COLLABORATION_CONFIGURATION; - - private static String HTTPD_PID_FILE; - - private static File pidFile; - - private static final HttpClient httpClient = new HttpClient(); - - private GetMethod getMethod; - - /** - * - */ - public HttpdCollaborationStatusMonitor(String _location, - String _httpdCollaborationURL, - String _httpdCollaborationConfiguration) { - HTTPD_PID_FILE = HttpdCollaborationUtil.endPathIfNecessary(_location) - + "var/run/httpd.pid"; - HTTPD_COLLABORATION_CONFIGURATION = _httpdCollaborationConfiguration; - this.sessionManager = SessionManager.getInstance(); - this.httpdCollaborationBecameUnavailable = false; - - pidFile = new File(HTTPD_PID_FILE); - this.getMethod = new GetMethod( - HttpdCollaborationUtil - .endPathIfNecessary(_httpdCollaborationURL)); - } - - public void statusHttpdCollaboration() - throws HttpdCollaborationNotRunningException, - HttpdCollaborationStatusException { - this.doesPidFileExist(); - - // "ping" the httpd process to ensure that it is actually running - this.verifyHttpdProcess(); - } - - private void doesPidFileExist() - throws HttpdCollaborationNotRunningException { - // verify the httpd-collaboration pid file exists. - - if (pidFile.exists() == false) { - // httpd-collaboration is not running - throw new HttpdCollaborationNotRunningException( - "the httpd-collaboration pid file does not exist: " - + pidFile.getAbsolutePath()); - } - } - - private void verifyHttpdProcess() - throws HttpdCollaborationNotRunningException, - HttpdCollaborationStatusException { - synchronized (this.getMethod) { - int statusCode = -1; - try { - statusCode = httpClient.executeMethod(getMethod); - } catch (HttpException e1) { - throw new HttpdCollaborationStatusException( - "Unable to execute GET against the httpd-collaboration server", - e1); - } catch (IOException e2) { - throw new HttpdCollaborationStatusException( - "Unable to read the response from the httpd-collaboration server", - e2); - } - - if ((statusCode == HttpStatus.SC_OK) == false) { - throw new HttpdCollaborationNotRunningException( - "httpd-collaboration is not available - received status = " - + statusCode); - } - } - } - - @Override - public void run() { - logger.debug("Verifying that httpd-collaboration is still available ..."); - String errorMessage = null; - - try { - this.statusHttpdCollaboration(); - } catch (HttpdCollaborationNotRunningException e1) { - logger.error("httpd-collaboration is not available", e1); - this.httpdCollaborationBecameUnavailable = true; - errorMessage = HttpdCollaborationUtil.encodeErrorMessage(e1); - } catch (HttpdCollaborationStatusException e2) { - logger.error( - "unable to determine if httpd-collaboration is still available!!!", - e2); - this.httpdCollaborationBecameUnavailable = true; - errorMessage = HttpdCollaborationUtil.encodeErrorMessage(e2); - } - - if (errorMessage == null && this.httpdCollaborationBecameUnavailable) { - // If we reach this point, httpd-collaboration became - // unavailable at some point in time; re-enable shared displays - // in CAVE for all users. - this.broadcastMessage(HTTPD_COLLABORATION_CONFIGURATION); - this.httpdCollaborationBecameUnavailable = false; - } else { - // Broadcast to all users that httpd-collaboration is no longer - // available; shared displays in CAVE will be disabled - this.broadcastMessage(errorMessage); - } - } - - private synchronized void broadcastMessage(String body) { - Message message = ConfigurationPacket.createMessage(body); - this.sessionManager.broadcast(message); - } -} \ No newline at end of file diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/iq/AbstractConfigHandler.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/iq/AbstractConfigHandler.java new file mode 100644 index 0000000000..447ba60350 --- /dev/null +++ b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/iq/AbstractConfigHandler.java @@ -0,0 +1,301 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.openfire.plugin.configuration.collaboration.iq; + +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; +import org.dom4j.Namespace; +import org.dom4j.tree.DefaultElement; +import org.jivesoftware.openfire.IQHandlerInfo; +import org.jivesoftware.openfire.PrivateStorage; +import org.jivesoftware.openfire.XMPPServer; +import org.jivesoftware.openfire.auth.UnauthorizedException; +import org.jivesoftware.openfire.disco.ServerFeaturesProvider; +import org.jivesoftware.openfire.handler.IQHandler; +import org.jivesoftware.util.JiveGlobals; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xmpp.packet.IQ; +import org.xmpp.packet.IQ.Type; +import org.xmpp.packet.JID; +import org.xmpp.packet.PacketError; +import org.xmpp.packet.PacketError.Condition; + +/** + * Base IQ handler for configuration over XMPP + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 12, 2014 2756 bclement Initial creation + * + *+ * + * @author bclement + * @version 1.0 + */ +public abstract class AbstractConfigHandler extends IQHandler implements + ServerFeaturesProvider { + + public static final String DATASERVER_USERS_KEY = "plugin.collaboration.dataserver.users"; + + public static final String QUERY_ELEMENT_NAME = "query"; + + public static final String COLLAB_XMLNS = "urn:uf:viz:collaboration"; + + private static final Logger log = LoggerFactory + .getLogger(AbstractConfigHandler.class); + + protected final IQHandlerInfo info; + + protected final List
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 10, 2014 2756 bclement Initial creation + * + *+ * + * @author bclement + * @version 1.0 + */ +public class DataAuthHandler extends AbstractConfigHandler { + + public static final String AUTH_QUERY_XMLNS = "urn:uf:viz:collaboration:iq:auth"; + + public static final String INFO_ELEMENT_NAME = "authinfo"; + + public static final String PUBKEY_ELEMENT_NAME = "publickey"; + + public static final String ALG_ATTRIBUTE = "algorithm"; + + public static final String JID_ATTRIBUTE = "jid"; + + public static final String SESSIONID_ATTRIBUTE = "sessionid"; + + private static final Logger log = LoggerFactory + .getLogger(DataAuthHandler.class); + + private final PubSubModule pubsub; + + /** + * @param moduleName + */ + public DataAuthHandler() { + super("Collaboration Auth Query Handler", Arrays + .asList(AUTH_QUERY_XMLNS), new IQHandlerInfo( + QUERY_ELEMENT_NAME, AUTH_QUERY_XMLNS)); + this.pubsub = XMPPServer.getInstance().getPubSubModule(); + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.openfire.plugin.configuration.collaboration.iq. + * AbstractConfigHandler#handleGet(org.xmpp.packet.IQ) + */ + @Override + protected IQ handleGet(IQ packet) throws UnauthorizedException { + JID from = packet.getFrom(); + String fromBare = from.toBareJID(); + Element queryElem = packet.getChildElement(); + String jid = queryElem.attributeValue(JID_ATTRIBUTE); + if (jid != null) { + if (!jid.equals(fromBare) && !isDataServerUser(from)) { + log.debug("User not authorized: " + from.toFullJID()); + throw new UnauthorizedException( + "User not authorized for service: " + + from.toFullJID()); + } + } else { + jid = fromBare; + } + JID target = new JID(jid); + String sessionId = queryElem.attributeValue(SESSIONID_ATTRIBUTE); + if (StringUtils.isBlank(sessionId)) { + String msg = "Missing attribute: " + SESSIONID_ATTRIBUTE; + log.debug(msg); + return createError(packet, new PacketError(Condition.bad_request, + PacketError.Type.modify, msg)); + } + Node node = pubsub.getNode(sessionId); + if (node == null) { + String msg = "No topic found for session: " + sessionId; + log.debug(msg); + return createError(packet, new PacketError(Condition.not_allowed, + PacketError.Type.cancel, msg)); + } + if (!isOwner(jid, node)){ + String msg = "User '" + jid + "' is not an owner of session '" + + sessionId + "'"; + log.debug(msg); + return createError(packet, new PacketError(Condition.not_allowed, + PacketError.Type.cancel, msg)); + } + return retrieve(packet, target.getNode(), + createElement(INFO_ELEMENT_NAME, COLLAB_XMLNS)); + } + + + /** + * @param jid + * @param node + * @return true if user with jid is owner of node + */ + private boolean isOwner(String jid, Node node) { + for (JID owner : node.getOwners()) { + if (jid.equals(owner.toBareJID())) { + return true; + } + } + return false; + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.openfire.plugin.configuration.collaboration.iq. + * AbstractConfigHandler#handleSet(org.xmpp.packet.IQ) + */ + @Override + protected IQ handleSet(IQ packet) { + Element queryElem = packet.getChildElement(); + Element infoElem; + Element pubkeyElem; + try { + infoElem = getChildElement(queryElem, INFO_ELEMENT_NAME, + COLLAB_XMLNS); + pubkeyElem = getChildElement(infoElem, PUBKEY_ELEMENT_NAME, + COLLAB_XMLNS); + } catch (Exception e) { + log.debug("Missing Required Element in packet: " + packet.toXML(), + e); + return createError(packet, new PacketError(Condition.bad_request, + PacketError.Type.modify, e.getLocalizedMessage())); + } + String pubKey = pubkeyElem.getText(); + if (StringUtils.isBlank(pubKey)) { + log.debug("Missing Public Key Text"); + return createError(packet, new PacketError(Condition.bad_request, + PacketError.Type.modify, "Missing Required Text Body")); + } + if (StringUtils.isBlank(pubkeyElem.attributeValue(ALG_ATTRIBUTE))) { + String msg = "Missing attribute: " + ALG_ATTRIBUTE; + return createError(packet, new PacketError(Condition.bad_request, + PacketError.Type.modify, msg)); + } + store(packet.getFrom().getNode(), infoElem); + return IQ.createResultIQ(packet); + } + +} diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/iq/HttpAddressHandler.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/iq/HttpAddressHandler.java new file mode 100644 index 0000000000..854ddc50c7 --- /dev/null +++ b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/iq/HttpAddressHandler.java @@ -0,0 +1,177 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.openfire.plugin.configuration.collaboration.iq; + +import java.util.Arrays; + +import org.apache.commons.lang.StringUtils; +import org.dom4j.Element; +import org.jivesoftware.openfire.IQHandlerInfo; +import org.jivesoftware.openfire.auth.UnauthorizedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xmpp.packet.IQ; +import org.xmpp.packet.JID; +import org.xmpp.packet.PacketError; +import org.xmpp.packet.PacketError.Condition; + + +/** + * IQ handler for dataservers to store URL configuration + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Feb 11, 2014 2756 bclement Initial creation + * + *+ * + * @author bclement + * @version 1.0 + */ +public class HttpAddressHandler extends AbstractConfigHandler { + + private static final Logger log = LoggerFactory + .getLogger(HttpAddressHandler.class); + + public static final String HTTP_QUERY_XMLNS = "urn:uf:viz:collaboration:iq:http"; + + public static final String HTTP_ELEMENT_NAME = "httpinfo"; + + public static final String URL_ELEMENT_NAME = "url"; + + public HttpAddressHandler() { + super("Collaboration Dataserver HTTP Address Handler", Arrays + .asList(HTTP_QUERY_XMLNS), new IQHandlerInfo( + QUERY_ELEMENT_NAME, HTTP_QUERY_XMLNS)); + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.openfire.plugin.configuration.collaboration.AbstractHandler + * #handleGet(org.xmpp.packet.IQ) + */ + @Override + protected IQ handleGet(IQ packet) throws UnauthorizedException { + String dataserver = getPrimaryDataServer(); + if (dataserver == null) { + // no dataserver configured, return empty response + return IQ.createResultIQ(packet); + } + JID target = new JID(dataserver); + return retrieve(packet, target.getNode(), + createElement(HTTP_ELEMENT_NAME, COLLAB_XMLNS)); + } + + /** + * Set http address for dataserver user with id. + * + * @param id + * @param url + */ + public void setHttpAddress(String id, String url) { + Element httpElem = createElement(HTTP_ELEMENT_NAME, COLLAB_XMLNS); + Element urlElement = createElement(URL_ELEMENT_NAME, COLLAB_XMLNS); + urlElement.setText(url); + urlElement.setParent(null); + httpElem.add(urlElement); + JID target = new JID(id); + store(target.getNode(), httpElem); + } + + /** + * Remove http address for dataserver user with id. + * + * @param id + * @param url + */ + public void removeHttpAddress(String id, String url) { + JID target = new JID(id); + store(target.getNode(), createElement(HTTP_ELEMENT_NAME, COLLAB_XMLNS)); + } + + /** + * Get http address for dataserver user with id. + * + * @param id + * @return + */ + public String getHttpAddress(String id) { + JID target = new JID(id); + Element respElem = storage.get(target.getNode(), + createElement(HTTP_ELEMENT_NAME, COLLAB_XMLNS)); + Element urlElem; + try { + urlElem = getChildElement(respElem, URL_ELEMENT_NAME, COLLAB_XMLNS); + } catch (Exception e) { + // missing url element, no url configured + return null; + } + String rval = urlElem.getText(); + if (StringUtils.isBlank(rval)) { + return null; + } + return rval.trim(); + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.openfire.plugin.configuration.collaboration.AbstractHandler + * #handleSet(org.xmpp.packet.IQ) + */ + @Override + protected IQ handleSet(IQ packet) throws UnauthorizedException { + JID from = packet.getFrom(); + if (!isDataServerUser(from)) { + String msg = "User not authorized for service: " + from.toFullJID(); + log.debug(msg); + throw new UnauthorizedException(msg); + } + Element queryElem = packet.getChildElement(); + Element infoElem; + Element urlElem; + try { + infoElem = getChildElement(queryElem, HTTP_ELEMENT_NAME, + COLLAB_XMLNS); + urlElem = getChildElement(infoElem, URL_ELEMENT_NAME, COLLAB_XMLNS); + } catch (Exception e) { + log.debug("Missing Required Element in packet: " + packet.toXML(), + e); + return createError(packet, new PacketError(Condition.bad_request, + PacketError.Type.modify, e.getLocalizedMessage())); + } + String url = urlElem.getText(); + if (StringUtils.isBlank(url)) { + log.debug("Missing HTTP URL Text"); + return createError(packet, new PacketError(Condition.bad_request, + PacketError.Type.modify, "Missing Required Text Body")); + } + store(packet.getFrom().getNode(), infoElem); + return IQ.createResultIQ(packet); + } + +} diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/listener/HttpdCollaborationSessionEventListener.java b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/listener/CollaborationSessionEventListener.java similarity index 69% rename from javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/listener/HttpdCollaborationSessionEventListener.java rename to javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/listener/CollaborationSessionEventListener.java index 5754237409..86da9ff5d1 100644 --- a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/listener/HttpdCollaborationSessionEventListener.java +++ b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/java/com/raytheon/openfire/plugin/configuration/collaboration/listener/CollaborationSessionEventListener.java @@ -25,16 +25,11 @@ import org.jivesoftware.openfire.MessageRouter; import org.jivesoftware.openfire.event.SessionEventListener; import org.jivesoftware.openfire.session.Session; import org.jivesoftware.util.TaskEngine; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.xmpp.packet.JID; import org.xmpp.packet.Message; import com.raytheon.openfire.plugin.configuration.collaboration.configuration.ConfigurationPacket; -import com.raytheon.openfire.plugin.configuration.collaboration.exception.HttpdCollaborationNotRunningException; -import com.raytheon.openfire.plugin.configuration.collaboration.exception.HttpdCollaborationStatusException; -import com.raytheon.openfire.plugin.configuration.collaboration.httpd.HttpdCollaborationStatusMonitor; -import com.raytheon.openfire.plugin.configuration.collaboration.util.HttpdCollaborationUtil; +import com.raytheon.openfire.plugin.configuration.collaboration.http.HttpStatusMonitor; /** * Impelements @{link SessionEventListener} to wait for new users to connect to @@ -48,23 +43,18 @@ import com.raytheon.openfire.plugin.configuration.collaboration.util.HttpdCollab * ------------ ---------- ----------- -------------------------- * Aug 07, 2012 bkowal Initial creation * Jan 06, 2013 2563 bclement replaced chat message with packet extension + * Feb 14, 2013 2756 bclement refactor for operation with generic http dataserver * * * * @author bkowal * @version 1.0 */ -public class HttpdCollaborationSessionEventListener implements - SessionEventListener { - private static final Logger logger = LoggerFactory - .getLogger(HttpdCollaborationSessionEventListener.class); - - // provided by the configuration - private String HTTPD_COLLABORATION_CONFIGURATION; +public class CollaborationSessionEventListener implements SessionEventListener { private static final int MSG_SEND_DELAY = 5000; - private HttpdCollaborationStatusMonitor httpdCollaborationStatusMonitor; + private HttpStatusMonitor statusMonitor; private JID serverAddress; @@ -73,9 +63,7 @@ public class HttpdCollaborationSessionEventListener implements /** * */ - public HttpdCollaborationSessionEventListener( - String _httpdCollaborationConfiguration) { - HTTPD_COLLABORATION_CONFIGURATION = _httpdCollaborationConfiguration; + public CollaborationSessionEventListener() { this.serverAddress = null; this.router = null; } @@ -129,6 +117,10 @@ public class HttpdCollaborationSessionEventListener implements */ @Override public void sessionCreated(Session session) { + String body = this.composeMessageBody(); + if (body == null) { + return; + } final Message message = ConfigurationPacket.createMessage(this .composeMessageBody()); message.setTo(session.getAddress()); @@ -157,27 +149,12 @@ public class HttpdCollaborationSessionEventListener implements private String composeMessageBody() { // Verify that httpd-collaboration is / is still running. - try { - this.httpdCollaborationStatusMonitor.statusHttpdCollaboration(); - } catch (HttpdCollaborationNotRunningException e1) { - logger.error("httpd-collaboration is not running.", e1); - return HttpdCollaborationUtil.encodeErrorMessage(e1); - } catch (HttpdCollaborationStatusException e2) { - logger.error( - "failed to determine the status of httpd-collaboration", e2); - return HttpdCollaborationUtil.encodeErrorMessage(e2); - } catch (Exception e3) { - logger.error("Unexpected exception occurred!", e3); - return HttpdCollaborationUtil.encodeErrorMessage(e3); - } - - return HTTPD_COLLABORATION_CONFIGURATION; + return statusMonitor.getCurrentUrlConfig(); } - public void setHttpdCollaborationStatusChecker( - HttpdCollaborationStatusMonitor httpdCollaborationStatusMonitor) { - this.httpdCollaborationStatusMonitor = httpdCollaborationStatusMonitor; - } + public void setHttpStatusChecker(HttpStatusMonitor httpStatusMonitor) { + this.statusMonitor = httpStatusMonitor; + } /** * @param serverAddress diff --git a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/plugin.xml b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/plugin.xml index ed1e35899e..ee9b9ac8d2 100644 --- a/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/plugin.xml +++ b/javaUtilities/com.raytheon.openfire.plugin.configuration.collaboration/plugin.xml @@ -1,23 +1,23 @@