Issue #2756 new collaboration openfire plugin and http service
new servlet http service that communicates with openfire for configuration new openfire plugin to reflect new http service openfire and http service no longer need to be on same machine moved http header parsing code from ogc to common util updated collaboration http code to prefer XML instead of HTML Former-commit-id:5b4f1e8288
[formerly ff23569984eee43927c10ca041ca7e0ca4d40a3b] Former-commit-id:f6b2827434
This commit is contained in:
parent
0fe9842582
commit
f0c89ef6c6
64 changed files with 3138 additions and 1041 deletions
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
|
@ -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
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -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<CollaborationHttpPersistedObject> objectEvents = new ArrayList<CollaborationHttpPersistedObject>();
|
||||
// parse out links of objects
|
||||
String htmlStr = new String(response.data);
|
||||
int searchIdx = 0;
|
||||
String searchStrStart = "<a href=\"";
|
||||
String objectEnding = ".obj";
|
||||
String searchStrEnd = "\">";
|
||||
int searchStrLen = searchStrStart.length();
|
||||
while (searchIdx > -1) {
|
||||
int previousIdx = searchIdx;
|
||||
int foundAt = htmlStr.indexOf(searchStrStart, searchIdx);
|
||||
// reset searchIdx to -1 until found
|
||||
searchIdx = -1;
|
||||
if (foundAt > previousIdx) {
|
||||
foundAt += searchStrLen;
|
||||
int endsAt = htmlStr.indexOf(searchStrEnd, foundAt);
|
||||
if (endsAt > foundAt) {
|
||||
String object = htmlStr.substring(foundAt, endsAt);
|
||||
if (object.endsWith(objectEnding)) {
|
||||
event.setResourcePath(objectPath + object);
|
||||
CollaborationHttpPersistedObject eventObject = retreiveStoredObject(event);
|
||||
if (eventObject != null) {
|
||||
objectEvents.add(eventObject);
|
||||
} else {
|
||||
// Object was deleted, abort
|
||||
return new AbstractDispatchingObjectEvent[0];
|
||||
}
|
||||
}
|
||||
searchIdx = endsAt + 1;
|
||||
}
|
||||
List<CollaborationHttpPersistedObject> objectEvents;
|
||||
try {
|
||||
if (response.contentType != null
|
||||
&& response.contentType.toLowerCase().contains("xml")) {
|
||||
objectEvents = parseXmlResponseData(objectPath, response.data);
|
||||
} else {
|
||||
objectEvents = parseHtmlResponseData(objectPath, response.data);
|
||||
}
|
||||
} catch (XMLStreamException e) {
|
||||
throw new CollaborationException("Error parsing response data", e);
|
||||
}
|
||||
if (objectEvents == null) {
|
||||
// Object was deleted, abort
|
||||
return new AbstractDispatchingObjectEvent[0];
|
||||
}
|
||||
|
||||
// Sort by creation time
|
||||
|
@ -306,10 +318,118 @@ public class CollaborationObjectEventStorage implements
|
|||
return events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse response from HTTP directory listing in xml format
|
||||
*
|
||||
* @param objectPath
|
||||
* @param responseData
|
||||
* @return null if object was deleted
|
||||
* @throws XMLStreamException
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
private List<CollaborationHttpPersistedObject> parseXmlResponseData(
|
||||
String objectPath, byte[] responseData) throws XMLStreamException,
|
||||
CollaborationException {
|
||||
|
||||
CollaborationHttpPersistedEvent event = new CollaborationHttpPersistedEvent();
|
||||
List<CollaborationHttpPersistedObject> objectEvents = new ArrayList<CollaborationHttpPersistedObject>();
|
||||
String text;
|
||||
boolean inFileTag = false;
|
||||
XMLStreamReader reader = staxFactory
|
||||
.createXMLStreamReader(new ByteArrayInputStream(responseData));
|
||||
while (reader.hasNext()) {
|
||||
int staxEvent = reader.next();
|
||||
switch (staxEvent) {
|
||||
case XMLStreamConstants.START_ELEMENT:
|
||||
String localName = reader.getLocalName();
|
||||
inFileTag = localName.equalsIgnoreCase("file");
|
||||
break;
|
||||
case XMLStreamConstants.CHARACTERS:
|
||||
text = reader.getText().trim();
|
||||
if (inFileTag && text.endsWith(".obj")) {
|
||||
event.setResourcePath(objectPath + text);
|
||||
CollaborationHttpPersistedObject eventObject = retreiveStoredObject(event);
|
||||
if (eventObject != null) {
|
||||
objectEvents.add(eventObject);
|
||||
} else {
|
||||
// Object was deleted, abort
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return objectEvents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse httpd HTML directory listing response
|
||||
*
|
||||
* @param objectPath
|
||||
* @param responseData
|
||||
* @return null if object was deleted
|
||||
* @throws XMLStreamException
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
private List<CollaborationHttpPersistedObject> parseHtmlResponseData(
|
||||
String objectPath, byte[] responseData) throws XMLStreamException,
|
||||
CollaborationException {
|
||||
CollaborationHttpPersistedEvent event = new CollaborationHttpPersistedEvent();
|
||||
List<CollaborationHttpPersistedObject> objectEvents = new ArrayList<CollaborationHttpPersistedObject>();
|
||||
String htmlStr = new String(responseData);
|
||||
int searchIdx = 0;
|
||||
String searchStrStart = "<a href=\"";
|
||||
String objectEnding = ".obj";
|
||||
String searchStrEnd = "\">";
|
||||
int searchStrLen = searchStrStart.length();
|
||||
while (searchIdx > -1) {
|
||||
int previousIdx = searchIdx;
|
||||
int foundAt = htmlStr.indexOf(searchStrStart, searchIdx);
|
||||
// reset searchIdx to -1 until found
|
||||
searchIdx = -1;
|
||||
if (foundAt > previousIdx) {
|
||||
foundAt += searchStrLen;
|
||||
int endsAt = htmlStr.indexOf(searchStrEnd, foundAt);
|
||||
if (endsAt > foundAt) {
|
||||
String object = htmlStr.substring(foundAt, endsAt);
|
||||
if (object.endsWith(objectEnding)) {
|
||||
event.setResourcePath(objectPath + object);
|
||||
CollaborationHttpPersistedObject eventObject = retreiveStoredObject(event);
|
||||
if (eventObject != null) {
|
||||
objectEvents.add(eventObject);
|
||||
} else {
|
||||
// Object was deleted, abort
|
||||
return null;
|
||||
}
|
||||
}
|
||||
searchIdx = endsAt + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return objectEvents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a MKCOL operation on httpd with DAV module.
|
||||
*
|
||||
* @deprecated MKCOL is only required for DAV (pre 14.3)
|
||||
*
|
||||
* @param folderPath
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
@Deprecated
|
||||
private void createFolder(String folderPath) throws CollaborationException {
|
||||
createFolder(URI.create(sessionDataURL + folderPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a MKCOL operation on httpd with DAV module.
|
||||
*
|
||||
* @deprecated MKCOL is only required for DAV (pre 14.3)
|
||||
*
|
||||
* @param folderPath
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
@Deprecated
|
||||
private void createFolder(URI folderPath) throws CollaborationException {
|
||||
HttpRequestBase mkcol = new HttpRequestBase() {
|
||||
@Override
|
||||
|
@ -325,6 +445,12 @@ public class CollaborationObjectEventStorage implements
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all files at and below uri
|
||||
*
|
||||
* @param uri
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
private void deleteResource(URI uri) throws CollaborationException {
|
||||
HttpClientResponse rsp = executeRequest(new HttpDelete(uri));
|
||||
// If request was success or resource doesn't exist, we are good
|
||||
|
@ -334,6 +460,13 @@ public class CollaborationObjectEventStorage implements
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute HTTP request
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
* @throws CollaborationException
|
||||
*/
|
||||
private HttpClientResponse executeRequest(HttpUriRequest request)
|
||||
throws CollaborationException {
|
||||
try {
|
||||
|
@ -343,14 +476,30 @@ public class CollaborationObjectEventStorage implements
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param code
|
||||
* @return true if code is a 200 level return code
|
||||
*/
|
||||
private boolean isSuccess(int code) {
|
||||
return code >= 200 && code < 300;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param code
|
||||
* @return true if resource does not exist on server
|
||||
*/
|
||||
private boolean isNotExists(int code) {
|
||||
return code == 404 || code == 410;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this error is related to MKCOL. MKCOL is only required for
|
||||
* DAV (pre 14.3)
|
||||
*
|
||||
* @param code
|
||||
* @return true if directory alread exists on server
|
||||
*/
|
||||
@Deprecated
|
||||
private boolean isDirExists(int code) {
|
||||
return code == 405 || code == 301;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ import com.raytheon.uf.common.util.ByteArrayOutputStreamPool.ByteArrayOutputStre
|
|||
* Mar 11, 2013 1786 mpduff Add https capability.
|
||||
* Jun 12, 2013 2102 njensen Better error handling when using
|
||||
* DynamicSerializeStreamHandler
|
||||
* Feb 17, 2014 2756 bclement added content type to response object
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -116,9 +117,12 @@ public class HttpClient {
|
|||
|
||||
public final byte[] data;
|
||||
|
||||
private HttpClientResponse(int code, byte[] data) {
|
||||
public final String contentType;
|
||||
|
||||
private HttpClientResponse(int code, byte[] data, String contentType) {
|
||||
this.code = code;
|
||||
this.data = data != null ? data : new byte[0];
|
||||
this.contentType = contentType;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -676,7 +680,7 @@ public class HttpClient {
|
|||
byteResult = ((DefaultInternalStreamHandler) handlerCallback).byteResult;
|
||||
}
|
||||
return new HttpClientResponse(resp.getStatusLine().getStatusCode(),
|
||||
byteResult);
|
||||
byteResult, getContentType(resp));
|
||||
} finally {
|
||||
if (ongoing != null) {
|
||||
ongoing.decrementAndGet();
|
||||
|
@ -684,6 +688,24 @@ public class HttpClient {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content type of response
|
||||
*
|
||||
* @param response
|
||||
* @return null if none found
|
||||
*/
|
||||
private static String getContentType(HttpResponse response) {
|
||||
String rval = null;
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
Header contentType = entity.getContentType();
|
||||
if (contentType != null) {
|
||||
rval = contentType.getValue();
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Streams the response content to the handler callback and closes the http
|
||||
* connection once finished.
|
||||
|
|
7
edexOsgi/com.raytheon.uf.common.http/.classpath
Normal file
7
edexOsgi/com.raytheon.uf.common.http/.classpath
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
28
edexOsgi/com.raytheon.uf.common.http/.project
Normal file
28
edexOsgi/com.raytheon.uf.common.http/.project
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.raytheon.uf.common.http</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,7 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
|
@ -0,0 +1,9 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Common Http
|
||||
Bundle-SymbolicName: com.raytheon.uf.common.http
|
||||
Bundle-Version: 1.14.0
|
||||
Bundle-Vendor: RAYTHEON
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Export-Package: com.raytheon.uf.common.http
|
||||
Require-Bundle: org.apache.commons.lang;bundle-version="2.3.0"
|
4
edexOsgi/com.raytheon.uf.common.http/build.properties
Normal file
4
edexOsgi/com.raytheon.uf.common.http/build.properties
Normal file
|
@ -0,0 +1,4 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
|
@ -17,14 +17,14 @@
|
|||
* 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;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Parses Accept-Encoding headers for HTTP requests
|
||||
* Parses Accept and Accept-Encoding headers for HTTP requests
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
* </pre>
|
||||
*
|
|
@ -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
|
||||
*
|
||||
* </pre>
|
||||
*
|
|
@ -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
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -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<String, String> getParameters(String paramStr) {
|
||||
Matcher m = PARAM_PATTERN.matcher(paramStr);
|
||||
Map<String, String> rval = new LinkedHashMap<String, String>();
|
||||
|
@ -141,6 +151,10 @@ public class MimeType {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param other
|
||||
* @return true if the mime type equals this one ignoring any parameters
|
||||
*/
|
||||
public boolean equalsIgnoreParams(MimeType other) {
|
||||
if (other == null) {
|
||||
return false;
|
||||
|
@ -166,10 +180,18 @@ public class MimeType {
|
|||
return parameters.get(paramName.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of parameters this mime type has
|
||||
*/
|
||||
public int getNumParams() {
|
||||
return parameters.size();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder sb = new StringBuilder(toStringWithoutParams());
|
||||
|
@ -186,6 +208,11 @@ public class MimeType {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format mime type excluding any parameters
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String toStringWithoutParams() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(this.type).append("/");
|
|
@ -143,4 +143,11 @@
|
|||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.raytheon.uf.common.http"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
</feature>
|
||||
|
|
|
@ -22,7 +22,8 @@ Require-Bundle: net.opengis;bundle-version="1.0.2",
|
|||
org.apache.commons.cxf,
|
||||
org.eclipse.jetty;bundle-version="7.6.9",
|
||||
com.raytheon.uf.common.dataplugin.level;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.edex.log;bundle-version="1.12.1174"
|
||||
com.raytheon.uf.edex.log;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.http
|
||||
Export-Package: com.raytheon.uf.edex.ogc.common,
|
||||
com.raytheon.uf.edex.ogc.common.db,
|
||||
com.raytheon.uf.edex.ogc.common.feature,
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
**/
|
||||
package com.raytheon.uf.edex.ogc.common;
|
||||
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
|
||||
/**
|
||||
* Response wrapper for OGC web services
|
||||
|
|
|
@ -14,9 +14,9 @@ import java.util.Map;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.ogc.common.InvalidVersionException;
|
||||
import com.raytheon.uf.edex.ogc.common.Version;
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
|
||||
/**
|
||||
* Utility methods and constants for GML version parsing and comparison
|
||||
|
|
|
@ -29,12 +29,12 @@ import org.geotools.feature.FeatureCollection;
|
|||
import org.opengis.feature.simple.SimpleFeature;
|
||||
import org.opengis.feature.simple.SimpleFeatureType;
|
||||
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.common.json.geo.GeoJsonUtil;
|
||||
import com.raytheon.uf.common.json.geo.GeoJsonUtilSimpleImpl;
|
||||
import com.raytheon.uf.common.json.geo.MixedFeatureCollection;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcResponse;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcResponse.TYPE;
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -47,11 +47,11 @@ import org.opengis.feature.simple.SimpleFeatureType;
|
|||
|
||||
import sun.misc.IOUtils;
|
||||
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcResponse;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcResponse.TYPE;
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
|
||||
/**
|
||||
* Convert simple features to shape files
|
||||
|
|
|
@ -24,8 +24,8 @@ import java.util.List;
|
|||
|
||||
import org.opengis.feature.simple.SimpleFeature;
|
||||
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcResponse;
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
|
||||
/**
|
||||
* Interface for converting simple features to different output formats
|
||||
|
|
|
@ -38,6 +38,9 @@ import javax.xml.stream.XMLStreamReader;
|
|||
import org.apache.commons.collections.map.CaseInsensitiveMap;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.raytheon.uf.common.http.AcceptHeaderParser;
|
||||
import com.raytheon.uf.common.http.AcceptHeaderValue;
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcException;
|
||||
|
|
|
@ -25,7 +25,8 @@ Require-Bundle: org.geotools;bundle-version="2.6.4",
|
|||
org.w3.xmlschema;bundle-version="1.0.0",
|
||||
com.raytheon.uf.common.pointdata;bundle-version="1.12.1174",
|
||||
org.apache.commons.collections;bundle-version="3.2.0",
|
||||
org.apache.commons.cxf;bundle-version="1.0.0"
|
||||
org.apache.commons.cxf;bundle-version="1.0.0",
|
||||
com.raytheon.uf.common.http
|
||||
Export-Package: com.raytheon.uf.edex.wfs,
|
||||
com.raytheon.uf.edex.wfs.feature,
|
||||
com.raytheon.uf.edex.wfs.filter,
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Map;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcBoundingBox;
|
||||
|
@ -30,7 +31,6 @@ import com.raytheon.uf.edex.ogc.common.OgcNamespace;
|
|||
import com.raytheon.uf.edex.ogc.common.OgcPrefix;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcResponse;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcTimeRange;
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.ogc.common.http.OgcHttpHandler;
|
||||
import com.raytheon.uf.edex.ogc.common.output.IOgcHttpResponse;
|
||||
import com.raytheon.uf.edex.ogc.common.output.OgcResponseOutput;
|
||||
|
|
|
@ -36,7 +36,7 @@ import net.opengis.wfs.v_1_1_0.ResultTypeType;
|
|||
import net.opengis.wfs.v_2_0_0.GetPropertyValueType;
|
||||
import net.opengis.wfs.v_2_0_0.StoredQueryType;
|
||||
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.wfs.WfsException;
|
||||
import com.raytheon.uf.edex.wfs.WfsException.Code;
|
||||
import com.raytheon.uf.edex.wfs.querystore.IStoredQueryCallback;
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
**/
|
||||
package com.raytheon.uf.edex.wfs.request;
|
||||
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcResponse;
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
|
||||
/**
|
||||
* Abstract base for WFS request wrappers
|
||||
|
|
|
@ -56,11 +56,11 @@ import net.opengis.wfs.v_1_1_0.GMLObjectTypeType;
|
|||
import net.opengis.wfs.v_1_1_0.OutputFormatListType;
|
||||
import net.opengis.wfs.v_1_1_0.WFSCapabilitiesType;
|
||||
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcNamespace;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcOperationInfo;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcServiceInfo;
|
||||
import com.raytheon.uf.edex.ogc.common.feature.GmlUtils;
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.wfs.IWfsProvider.WfsOpType;
|
||||
import com.raytheon.uf.edex.wfs.WfsException;
|
||||
import com.raytheon.uf.edex.wfs.reg.WfsRegistryImpl;
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.opengis.feature.simple.SimpleFeature;
|
|||
import org.springframework.context.ApplicationContext;
|
||||
import org.w3.xmlschema.Schema;
|
||||
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.core.EDEXUtil;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcException;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcOperationInfo;
|
||||
|
@ -55,7 +56,6 @@ import com.raytheon.uf.edex.ogc.common.OgcServiceInfo;
|
|||
import com.raytheon.uf.edex.ogc.common.feature.GmlUtils;
|
||||
import com.raytheon.uf.edex.ogc.common.feature.SimpleFeatureFormatter;
|
||||
import com.raytheon.uf.edex.ogc.common.http.EndpointInfo;
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.ogc.common.http.OgcHttpHandler;
|
||||
import com.raytheon.uf.edex.ogc.common.output.IOgcHttpResponse;
|
||||
import com.raytheon.uf.edex.ogc.common.output.OgcResponseOutput;
|
||||
|
|
|
@ -54,11 +54,11 @@ import net.opengis.wfs.v_2_0_0.FeatureTypeListType;
|
|||
import net.opengis.wfs.v_2_0_0.FeatureTypeType;
|
||||
import net.opengis.wfs.v_2_0_0.WFSCapabilitiesType;
|
||||
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcNamespace;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcOperationInfo;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcServiceInfo;
|
||||
import com.raytheon.uf.edex.ogc.common.feature.GmlUtils;
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.wfs.IWfsProvider.WfsOpType;
|
||||
import com.raytheon.uf.edex.wfs.WfsException;
|
||||
import com.raytheon.uf.edex.wfs.reg.WfsRegistryImpl;
|
||||
|
|
|
@ -67,6 +67,7 @@ import org.w3.xmlschema.Schema;
|
|||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import com.raytheon.uf.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.core.EDEXUtil;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcException;
|
||||
import com.raytheon.uf.edex.ogc.common.OgcOperationInfo;
|
||||
|
@ -77,7 +78,6 @@ import com.raytheon.uf.edex.ogc.common.OgcServiceInfo;
|
|||
import com.raytheon.uf.edex.ogc.common.feature.GmlUtils;
|
||||
import com.raytheon.uf.edex.ogc.common.feature.SimpleFeatureFormatter;
|
||||
import com.raytheon.uf.edex.ogc.common.http.EndpointInfo;
|
||||
import com.raytheon.uf.edex.ogc.common.http.MimeType;
|
||||
import com.raytheon.uf.edex.ogc.common.http.OgcHttpHandler;
|
||||
import com.raytheon.uf.edex.ogc.common.output.IOgcHttpResponse;
|
||||
import com.raytheon.uf.edex.ogc.common.output.OgcResponseOutput;
|
||||
|
|
7
javaUtilities/collaboration.dataserver/.classpath
Normal file
7
javaUtilities/collaboration.dataserver/.classpath
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
28
javaUtilities/collaboration.dataserver/.project
Normal file
28
javaUtilities/collaboration.dataserver/.project
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>collaboration.dataserver</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,7 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
10
javaUtilities/collaboration.dataserver/META-INF/MANIFEST.MF
Normal file
10
javaUtilities/collaboration.dataserver/META-INF/MANIFEST.MF
Normal file
|
@ -0,0 +1,10 @@
|
|||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Dataserver
|
||||
Bundle-SymbolicName: collaboration.dataserver
|
||||
Bundle-Version: 1.14.0
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Require-Bundle: org.eclipse.jetty,
|
||||
com.raytheon.uf.common.util,
|
||||
org.jivesoftware.smack,
|
||||
com.raytheon.uf.common.http
|
4
javaUtilities/collaboration.dataserver/build.properties
Normal file
4
javaUtilities/collaboration.dataserver/build.properties
Normal file
|
@ -0,0 +1,4 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
|
@ -0,0 +1,2 @@
|
|||
xmpp.username=dataserver
|
||||
xmpp.password=password
|
|
@ -0,0 +1,5 @@
|
|||
port=9682
|
||||
datapath=/session_data/
|
||||
logdir=logs
|
||||
logname=serverlog_yyyy_mm_dd.log
|
||||
xmpp.server=localhost
|
|
@ -0,0 +1,273 @@
|
|||
/**
|
||||
* 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.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Global configuration for dataserver
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 5, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 5, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 5, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 6, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class FileManager {
|
||||
|
||||
private static final int BUFFER_SIZE = 1024 * 256; // 256K
|
||||
|
||||
private static final ThreadLocal<byte[]> localBuffer = new ThreadLocal<byte[]>() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.ThreadLocal#initialValue()
|
||||
*/
|
||||
@Override
|
||||
protected byte[] initialValue() {
|
||||
return new byte[BUFFER_SIZE];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private static final KeyLocker<File> locker = new KeyLocker<File>();
|
||||
|
||||
private final File base;
|
||||
|
||||
/**
|
||||
* @param base
|
||||
* base storage directory
|
||||
*/
|
||||
public FileManager(File base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
/**
|
||||
* simple container to associate a file lock with it's access mode
|
||||
*/
|
||||
private static class UsedLock {
|
||||
public final KeyLock<File> lock;
|
||||
|
||||
public final boolean readOnly;
|
||||
|
||||
public UsedLock(KeyLock<File> lock, boolean readOnly) {
|
||||
this.lock = lock;
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write inputstream to file system
|
||||
*
|
||||
* @param in
|
||||
* @param file
|
||||
* @throws IOException
|
||||
* @throws RestException
|
||||
*/
|
||||
public void writeFile(InputStream in, File file) throws IOException,
|
||||
RestException {
|
||||
OutputStream out = null;
|
||||
List<UsedLock> locks = null;
|
||||
KeyLock<File> targetLock = null;
|
||||
try {
|
||||
File parent = file.getParentFile();
|
||||
// lock all files starting at child of base going to parent
|
||||
locks = getCreateLocks(parent);
|
||||
// lock target file for modification
|
||||
targetLock = locker.getLock(file);
|
||||
targetLock.lock();
|
||||
createDirs(locks);
|
||||
out = new FileOutputStream(file);
|
||||
copy(in, out);
|
||||
} finally {
|
||||
// unlock in reverse order
|
||||
if (targetLock != null) {
|
||||
targetLock.unlock();
|
||||
}
|
||||
unlock(locks);
|
||||
in.close();
|
||||
if (out != null) {
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Each item in locks represents a node in a directory path. Attempts to
|
||||
* create each node in order.
|
||||
*
|
||||
* @param locks
|
||||
* @throws IOException
|
||||
*/
|
||||
private void createDirs(List<UsedLock> locks) throws IOException {
|
||||
for (UsedLock lock : locks) {
|
||||
File f = lock.lock.getKey();
|
||||
if (!f.exists()) {
|
||||
if (!f.mkdir()) {
|
||||
throw new IOException("Unable to create file: "
|
||||
+ f.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock each file lock in reverse order
|
||||
*
|
||||
* @param locks
|
||||
*/
|
||||
private void unlock(List<UsedLock> locks) {
|
||||
if (locks != null) {
|
||||
ListIterator<UsedLock> iter = locks.listIterator(locks.size());
|
||||
while (iter.hasPrevious()) {
|
||||
UsedLock ul = iter.previous();
|
||||
if (ul.readOnly) {
|
||||
ul.lock.readUnlock();
|
||||
} else {
|
||||
ul.lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of write file locks for each directory from the base to the
|
||||
* target directory
|
||||
*
|
||||
* @param targetDirectory
|
||||
* @return
|
||||
* @throws RestException
|
||||
*/
|
||||
private List<UsedLock> getCreateLocks(File targetDirectory)
|
||||
throws RestException {
|
||||
List<KeyLock<File>> locks = new ArrayList<KeyLock<File>>();
|
||||
// walk backwards getting locks for each node
|
||||
while (!base.equals(targetDirectory)) {
|
||||
locks.add(locker.getLock(targetDirectory));
|
||||
targetDirectory = targetDirectory.getParentFile();
|
||||
}
|
||||
List<UsedLock> rval = new ArrayList<UsedLock>(locks.size());
|
||||
// reverse iterate so we lock in the correct order
|
||||
ListIterator<KeyLock<File>> iter = locks.listIterator(locks.size());
|
||||
while (iter.hasPrevious()) {
|
||||
KeyLock<File> lock = iter.previous();
|
||||
File f = lock.getKey();
|
||||
if (!f.exists()) {
|
||||
lock.lock();
|
||||
rval.add(new UsedLock(lock, false));
|
||||
} else if (f.isDirectory()) {
|
||||
lock.readLock();
|
||||
rval.add(new UsedLock(lock, true));
|
||||
} else {
|
||||
// file exists but is not a directory
|
||||
throw new RestException(HttpServletResponse.SC_CONFLICT,
|
||||
"Resource already exists: " + f.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output file to stream
|
||||
*
|
||||
* @param file
|
||||
* @param out
|
||||
* @throws IOException
|
||||
* @throws RestException
|
||||
*/
|
||||
public void readFile(File file, OutputStream out) throws IOException,
|
||||
RestException {
|
||||
InputStream in = null;
|
||||
List<UsedLock> locks = null;
|
||||
try {
|
||||
locks = getReadLocks(file);
|
||||
if ( !file.exists()){
|
||||
throw new RestException(HttpServletResponse.SC_NOT_FOUND,
|
||||
"No Such File: " + file.getAbsoluteFile());
|
||||
}
|
||||
in = new FileInputStream(file);
|
||||
copy(in, out);
|
||||
} finally {
|
||||
unlock(locks);
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of read only file locks for each file from the base to the
|
||||
* target file
|
||||
*
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
private List<UsedLock> getReadLocks(File file) {
|
||||
List<KeyLock<File>> locks = new ArrayList<KeyLock<File>>();
|
||||
// walk backwards getting locks for each node
|
||||
while (!base.equals(file)) {
|
||||
locks.add(locker.getLock(file));
|
||||
file = file.getParentFile();
|
||||
}
|
||||
List<UsedLock> rval = new ArrayList<UsedLock>(locks.size());
|
||||
// reverse iterate so we lock in the correct order
|
||||
ListIterator<KeyLock<File>> iter = locks.listIterator(locks.size());
|
||||
while (iter.hasPrevious()) {
|
||||
KeyLock<File> lock = iter.previous();
|
||||
lock.readLock();
|
||||
rval.add(new UsedLock(lock, true));
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output contents of directory to stream in XML format
|
||||
*
|
||||
* @param directory
|
||||
* @param out
|
||||
* @throws IOException
|
||||
* @throws RestException
|
||||
*/
|
||||
public void readDirectoryAsXml(File directory, OutputStream out)
|
||||
throws IOException, RestException {
|
||||
List<UsedLock> locks = null;
|
||||
Writer w = null;
|
||||
try {
|
||||
locks = getReadLocks(directory);
|
||||
if (!directory.exists()) {
|
||||
// someone else modified it while waiting for lock
|
||||
throw new RestException(HttpServletResponse.SC_NOT_FOUND,
|
||||
"No Such Directory: " + directory.getAbsolutePath());
|
||||
}
|
||||
w = new OutputStreamWriter(out, "UTF-8");
|
||||
w.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
|
||||
w.write("<Contents xmlns=\"urn:uf:viz:collaboration\">");
|
||||
for (File f : directory.listFiles()) {
|
||||
if (f.isDirectory()) {
|
||||
writeTextTag(w, "Directory", f.getName());
|
||||
} else {
|
||||
writeTextTag(w, "File", f.getName());
|
||||
}
|
||||
}
|
||||
w.write("</Contents>");
|
||||
} finally {
|
||||
unlock(locks);
|
||||
if (w != null) {
|
||||
w.flush();
|
||||
w.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write tag with text element to writer
|
||||
*
|
||||
* @param w
|
||||
* @param tagName
|
||||
* @param text
|
||||
* @throws IOException
|
||||
*/
|
||||
private void writeTextTag(Writer w, String tagName, String text)
|
||||
throws IOException {
|
||||
w.write("<");
|
||||
w.write(tagName);
|
||||
w.write(">");
|
||||
w.write(text);
|
||||
w.write("</");
|
||||
w.write(tagName);
|
||||
w.write(">");
|
||||
}
|
||||
|
||||
/**
|
||||
* Output contents of directory to stream in HTML format
|
||||
*
|
||||
* @param directory
|
||||
* @param out
|
||||
* @throws IOException
|
||||
* @throws RestException
|
||||
*/
|
||||
public void readDirectoryAsHtml(File directory, OutputStream out)
|
||||
throws IOException, RestException {
|
||||
List<UsedLock> locks = null;
|
||||
Writer w = null;
|
||||
try {
|
||||
locks = getReadLocks(directory);
|
||||
if (!directory.exists()) {
|
||||
// someone else modified it while waiting for lock
|
||||
throw new RestException(HttpServletResponse.SC_NOT_FOUND,
|
||||
"No Such Directory: " + directory.getAbsolutePath());
|
||||
}
|
||||
w = new OutputStreamWriter(out, "UTF-8");
|
||||
w.write("<!DOCTYPE html>\n");
|
||||
w.write("<html><body>");
|
||||
for (File f : directory.listFiles()) {
|
||||
String name = f.getName();
|
||||
if (f.isDirectory() && !name.endsWith("/")) {
|
||||
name = name + "/";
|
||||
}
|
||||
writeLinkTag(w, name);
|
||||
}
|
||||
w.write("</body></html>");
|
||||
} finally {
|
||||
unlock(locks);
|
||||
if (w != null) {
|
||||
w.flush();
|
||||
w.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write html link reference tag to writer
|
||||
*
|
||||
* @param w
|
||||
* @param href
|
||||
* @throws IOException
|
||||
*/
|
||||
private void writeLinkTag(Writer w, String href) throws IOException {
|
||||
w.write("<a href=\"");
|
||||
w.write(href);
|
||||
w.write("\">");
|
||||
w.write(href);
|
||||
w.write("</a></br>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy bytes from input to output
|
||||
*
|
||||
* @param in
|
||||
* @param out
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void copy(InputStream in, OutputStream out)
|
||||
throws IOException {
|
||||
byte[] buff = localBuffer.get();
|
||||
int len;
|
||||
while ((len = in.read(buff)) != -1) {
|
||||
out.write(buff, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete target file and all children
|
||||
*
|
||||
* @param file
|
||||
* @throws IOException
|
||||
* @throws RestException
|
||||
*/
|
||||
public void delete(File file) throws IOException, RestException {
|
||||
List<UsedLock> parentLocks = null;
|
||||
KeyLock<File> targetLock = null;
|
||||
try {
|
||||
File parent = file.getParentFile();
|
||||
parentLocks = getReadLocks(parent);
|
||||
targetLock = locker.getLock(file);
|
||||
targetLock.lock();
|
||||
if (!file.exists()) {
|
||||
throw new RestException(HttpServletResponse.SC_NOT_FOUND,
|
||||
"No Such Resource: " + file.getAbsolutePath());
|
||||
}
|
||||
// we don't have to lock children since we have a write lock on the
|
||||
// directory
|
||||
deleteRecursive(file);
|
||||
} finally {
|
||||
if (targetLock != null) {
|
||||
targetLock.unlock();
|
||||
}
|
||||
unlock(parentLocks);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive method to delete file and children
|
||||
*
|
||||
* @param file
|
||||
* @throws IOException
|
||||
*/
|
||||
private void deleteRecursive(File file) throws IOException {
|
||||
if (file.isDirectory()) {
|
||||
for (File sub : file.listFiles()) {
|
||||
deleteRecursive(sub);
|
||||
}
|
||||
}
|
||||
if (!file.delete()) {
|
||||
throw new IOException("Unable to delete file: "
|
||||
+ file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -17,13 +17,10 @@
|
|||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.openfire.plugin.configuration.collaboration.util;
|
||||
|
||||
import java.io.File;
|
||||
package com.raytheon.collaboration.dataserver;
|
||||
|
||||
/**
|
||||
* Various utility methods that are utilized by the Httpd Collaboration plugin
|
||||
* that do not require a class to be instantiated.
|
||||
* Exceptions for web service errors to be returned to the client
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @return the code
|
||||
*/
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 14, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 14, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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 "<query xmlns=\"urn:uf:viz:collaboration:iq:http\">"
|
||||
+ "<httpinfo xmlns=\"urn:uf:viz:collaboration\">"
|
||||
+ "<url>" + dataServerUrl + "</url></httpinfo></query>";
|
||||
}
|
||||
};
|
||||
packet.setType(Type.SET);
|
||||
try {
|
||||
Packet reply = SyncPacketSend.getReply(conn, packet,
|
||||
PACKET_SEND_TIMEOUT);
|
||||
log.debug("URL configuration set response: " + reply.toXML());
|
||||
} catch (XMPPException e) {
|
||||
log.warn("Problem sending URL configuration packet", e);
|
||||
}
|
||||
while (conn.isConnected()) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Server connection thread interrupted", e);
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* disconnect from XMPP server
|
||||
*/
|
||||
public void disconnect() {
|
||||
log.debug("Disconnecting from XMPP server");
|
||||
conn.disconnect();
|
||||
}
|
||||
|
||||
}
|
12
javaUtilities/collaboration.dataserver/start.sh
Executable file
12
javaUtilities/collaboration.dataserver/start.sh
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
|
||||
(cd $(dirname "$0")
|
||||
PIDFILE=collabserver.pid
|
||||
if [[ -e $PIDFILE ]]
|
||||
then
|
||||
echo "PID file already exists at $PIDFILE, exiting"
|
||||
exit 1
|
||||
fi
|
||||
nohup java -server -jar collabserver.jar &
|
||||
echo $! > $PIDFILE
|
||||
)
|
10
javaUtilities/collaboration.dataserver/stop.sh
Executable file
10
javaUtilities/collaboration.dataserver/stop.sh
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
(cd $(dirname "$0")
|
||||
PIDFILE=collabserver.pid
|
||||
if [[ -e $PIDFILE ]]
|
||||
then
|
||||
kill `cat $PIDFILE`
|
||||
rm $PIDFILE
|
||||
fi
|
||||
)
|
|
@ -2,10 +2,9 @@ Manifest-Version: 1.0
|
|||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: CollaborationConfiguration
|
||||
Bundle-SymbolicName: com.raytheon.openfire.plugin.configuration.collaboration;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Version: 1.14.0
|
||||
Bundle-Vendor: RAYTHEON
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Require-Bundle: org.jivesoftware.openfire;bundle-version="3.7.1",
|
||||
org.apache.commons.configuration;bundle-version="1.6.0",
|
||||
org.apache.commons.collections;bundle-version="3.2.0",
|
||||
org.apache.http;bundle-version="4.1.2"
|
||||
|
|
|
@ -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;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.openfire.IQRouter;
|
||||
import org.jivesoftware.openfire.XMPPServer;
|
||||
import org.jivesoftware.openfire.container.Plugin;
|
||||
import org.jivesoftware.openfire.container.PluginManager;
|
||||
import org.jivesoftware.openfire.disco.IQDiscoInfoHandler;
|
||||
import org.jivesoftware.openfire.event.SessionEventDispatcher;
|
||||
import org.jivesoftware.util.JiveGlobals;
|
||||
import org.jivesoftware.util.TaskEngine;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xmpp.packet.JID;
|
||||
|
||||
import com.raytheon.openfire.plugin.configuration.collaboration.configuration.ConfigurationPacket;
|
||||
import com.raytheon.openfire.plugin.configuration.collaboration.http.HttpStatusMonitor;
|
||||
import com.raytheon.openfire.plugin.configuration.collaboration.iq.AbstractConfigHandler;
|
||||
import com.raytheon.openfire.plugin.configuration.collaboration.iq.DataAuthHandler;
|
||||
import com.raytheon.openfire.plugin.configuration.collaboration.iq.HttpAddressHandler;
|
||||
import com.raytheon.openfire.plugin.configuration.collaboration.listener.CollaborationSessionEventListener;
|
||||
|
||||
/**
|
||||
* The main plugin class for the AWIPS II Collaboration HTTP Configuration
|
||||
* plugin; creates and configures an openfire listener and the http monitor.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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<AbstractConfigHandler> handlers) {
|
||||
IQRouter router = server.getIQRouter();
|
||||
IQDiscoInfoHandler infoHandler = server.getIQDiscoInfoHandler();
|
||||
for (AbstractConfigHandler handler : handlers) {
|
||||
Iterator<String> iter = handler.getFeatures();
|
||||
while (iter.hasNext()) {
|
||||
infoHandler.addServerFeature(iter.next());
|
||||
}
|
||||
router.addHandler(handler);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.jivesoftware.openfire.container.Plugin#initializePlugin(org.jivesoftware
|
||||
* .openfire.container.PluginManager, java.io.File)
|
||||
*/
|
||||
@Override
|
||||
public void initializePlugin(PluginManager manager, File arg1) {
|
||||
XMPPServer server = XMPPServer.getInstance();
|
||||
|
||||
DataAuthHandler authHandler = new DataAuthHandler();
|
||||
HttpAddressHandler addressHandler = new HttpAddressHandler();
|
||||
registerConfigHandlers(server,
|
||||
Arrays.asList(authHandler, addressHandler));
|
||||
|
||||
/* Retrieve openfire components. */
|
||||
JID serverId = new JID(server.getServerInfo().getXMPPDomain());
|
||||
|
||||
/* The http status monitor */
|
||||
this.httpStatusMonitor = new HttpStatusMonitor(addressHandler, serverId);
|
||||
|
||||
/* Create a new listener. */
|
||||
this.listener = new CollaborationSessionEventListener();
|
||||
|
||||
/* Initialize the listener. */
|
||||
this.listener
|
||||
.setHttpStatusChecker(this.httpStatusMonitor);
|
||||
this.listener.setServerAddress(serverId);
|
||||
this.listener.setRouter(server.getMessageRouter());
|
||||
|
||||
/* Make it possible for the listener to receive events. */
|
||||
SessionEventDispatcher.addListener(this.listener);
|
||||
this.scheduleStatusMonitor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the http 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.httpStatusMonitor,
|
||||
MONITOR_DELAY_MS, this.getHttpMonitorInterval());
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the scheduled http collaboration status monitor if it has been
|
||||
* scheduled.
|
||||
*/
|
||||
private synchronized void stopStatusMonitor() {
|
||||
if (this.monitorTaskEngine == null) {
|
||||
return;
|
||||
}
|
||||
this.monitorTaskEngine
|
||||
.cancelScheduledTask(this.httpStatusMonitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the configurable interval for the amount of time between executions
|
||||
* of the http collaboration status monitor
|
||||
*
|
||||
* @param _interval
|
||||
* the interval in milliseconds
|
||||
*/
|
||||
public void setHttpMonitorInterval(long _interval) {
|
||||
long originalInterval = this.getHttpMonitorInterval();
|
||||
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 getHttpMonitorInterval() {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set white list of accounts that belong to dataservers. The first server
|
||||
* in the list is treated as the primary dataserver.
|
||||
*
|
||||
* @param whiteList
|
||||
*/
|
||||
public void setDataserverUsers(String whiteList) {
|
||||
JiveGlobals
|
||||
.setProperty(AbstractConfigHandler.DATASERVER_USERS_KEY, whiteList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return white list of accounts that belong to dataservers. The first
|
||||
* server in the list is treated as the primary dataserver.
|
||||
*/
|
||||
public String getDataserverUsers() {
|
||||
return JiveGlobals
|
||||
.getProperty(AbstractConfigHandler.DATASERVER_USERS_KEY, "");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,278 +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;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.apache.commons.configuration.ConfigurationException;
|
||||
import org.jivesoftware.openfire.MessageRouter;
|
||||
import org.jivesoftware.openfire.XMPPServer;
|
||||
import org.jivesoftware.openfire.container.Plugin;
|
||||
import org.jivesoftware.openfire.container.PluginManager;
|
||||
import org.jivesoftware.openfire.event.SessionEventDispatcher;
|
||||
import org.jivesoftware.util.JiveGlobals;
|
||||
import org.jivesoftware.util.TaskEngine;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.xmpp.packet.JID;
|
||||
|
||||
import com.raytheon.openfire.plugin.configuration.collaboration.configuration.ConfigurationPacket;
|
||||
import com.raytheon.openfire.plugin.configuration.collaboration.configuration.HttpdCollaborationConfiguration;
|
||||
import com.raytheon.openfire.plugin.configuration.collaboration.httpd.HttpdCollaborationConfReader;
|
||||
import com.raytheon.openfire.plugin.configuration.collaboration.httpd.HttpdCollaborationStatusMonitor;
|
||||
import com.raytheon.openfire.plugin.configuration.collaboration.listener.HttpdCollaborationSessionEventListener;
|
||||
|
||||
/**
|
||||
* The main plugin class for the AWIPS II Httpd Collaboration Configuration
|
||||
* plugin; creates and configures an openfire listener and the httpd monitor.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -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, '=');
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 07, 2012 bkowal Initial creation
|
||||
* Jan 06, 2013 2563 bclement removed config preamble
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 10, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 30, 2012 bkowal Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 30, 2012 bkowal Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 7, 2012 bkowal Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 2012 bkowal Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 26, 2012 bkowal Initial creation
|
||||
* Jan 06, 2013 2563 bclement replaced chat message with packet extension
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 12, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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<String> features;
|
||||
|
||||
protected final PrivateStorage storage;
|
||||
|
||||
|
||||
/**
|
||||
* @param moduleName
|
||||
* display name for handler
|
||||
* @param features
|
||||
* xmlns strings for features
|
||||
* @param info
|
||||
* qualified name registration information
|
||||
*/
|
||||
public AbstractConfigHandler(String moduleName, List<String> features,
|
||||
IQHandlerInfo info) {
|
||||
super(moduleName);
|
||||
this.info = info;
|
||||
this.features = features;
|
||||
this.storage = XMPPServer.getInstance().getPrivateStorage();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.jivesoftware.openfire.handler.IQHandler#getInfo()
|
||||
*/
|
||||
@Override
|
||||
public IQHandlerInfo getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.jivesoftware.openfire.handler.IQHandler#handleIQ(org.xmpp.packet.IQ)
|
||||
*/
|
||||
@Override
|
||||
public IQ handleIQ(IQ packet) throws UnauthorizedException {
|
||||
Type type = packet.getType();
|
||||
IQ rval;
|
||||
switch (type) {
|
||||
case get:
|
||||
rval = handleGet(packet);
|
||||
break;
|
||||
case set:
|
||||
rval = handleSet(packet);
|
||||
break;
|
||||
default:
|
||||
rval = createError(packet, new PacketError(Condition.bad_request));
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process get request
|
||||
*
|
||||
* @param packet
|
||||
* request packet
|
||||
* @return
|
||||
* @throws UnauthorizedException
|
||||
*/
|
||||
abstract protected IQ handleGet(IQ packet) throws UnauthorizedException;
|
||||
|
||||
/**
|
||||
* Process set request
|
||||
*
|
||||
* @param packet
|
||||
* request packet
|
||||
* @return
|
||||
* @throws UnauthorizedException
|
||||
*/
|
||||
abstract protected IQ handleSet(IQ packet) throws UnauthorizedException;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.jivesoftware.openfire.disco.ServerFeaturesProvider#getFeatures()
|
||||
*/
|
||||
@Override
|
||||
public Iterator<String> getFeatures() {
|
||||
return features.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create error response packet
|
||||
*
|
||||
* @param request
|
||||
* @param error
|
||||
* @return
|
||||
*/
|
||||
protected static IQ createError(IQ request, PacketError error) {
|
||||
Element child = request.getChildElement();
|
||||
child.setParent(null);
|
||||
IQ rval = IQ.createResultIQ(request);
|
||||
rval.setType(Type.error);
|
||||
rval.setChildElement(child);
|
||||
rval.setError(error);
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first child of parent found with qualified name
|
||||
*
|
||||
* @param parent
|
||||
* @param name
|
||||
* @param namespace
|
||||
* @return
|
||||
* @throws Exception
|
||||
* if no child can be found
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static Element getChildElement(Element parent, String name,
|
||||
String namespace) throws Exception {
|
||||
Element rval = null;
|
||||
Iterator<Element> iter = parent.elementIterator();
|
||||
while (iter.hasNext()) {
|
||||
Element child = iter.next();
|
||||
if (child != null && child.getName().equals(name)
|
||||
&& child.getNamespace().getURI().equals(namespace)) {
|
||||
rval = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rval == null) {
|
||||
log.debug("Missing Data Element: " + parent.asXML());
|
||||
String msg = "Missing Required Child Element: " + namespace + " "
|
||||
+ name;
|
||||
throw new Exception(msg);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all child elements from e
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static void removeChildren(Element e) {
|
||||
Iterator<Element> iter = e.elementIterator();
|
||||
while (iter.hasNext()) {
|
||||
e.remove(iter.next());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* @return true if id is in the list of dataserver users
|
||||
*/
|
||||
protected static boolean isDataServerUser(JID id) {
|
||||
String usersStr = JiveGlobals.getProperty(DATASERVER_USERS_KEY, "");
|
||||
// this will work if the dataserver user is set to a single account or a
|
||||
// comma separated list or is blank
|
||||
for (String user : StringUtils.split(usersStr, ',')) {
|
||||
if (StringUtils.isBlank(user)) {
|
||||
continue;
|
||||
}
|
||||
user = user.trim();
|
||||
if (id.toBareJID().equals(user)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the primary dataserver which is the first item in the list of
|
||||
* dataserver users
|
||||
*
|
||||
* @return null if none found
|
||||
*/
|
||||
public static String getPrimaryDataServer() {
|
||||
String usersStr = JiveGlobals.getProperty(DATASERVER_USERS_KEY, "");
|
||||
String[] users = StringUtils.split(usersStr, ',');
|
||||
if (users.length < 1) {
|
||||
return null;
|
||||
}
|
||||
// primary server is the only one or first in list
|
||||
return users[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve data from private storage
|
||||
*
|
||||
* @param requestPacket
|
||||
* request IQ for data
|
||||
* @param id
|
||||
* user id that data is stored under
|
||||
* @param key
|
||||
* empty xml element with qualified name
|
||||
* @return
|
||||
*/
|
||||
protected IQ retrieve(IQ requestPacket, String id, Element key) {
|
||||
Element queryElem = requestPacket.getChildElement();
|
||||
Element respElem = storage.get(id, key);
|
||||
IQ rval = IQ.createResultIQ(requestPacket);
|
||||
queryElem.setParent(null);
|
||||
removeChildren(queryElem);
|
||||
queryElem.add(respElem);
|
||||
rval.setChildElement(queryElem);
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store to private data. NOTE: only child XML elements of the root data
|
||||
* element will be retrievable. No attributes in the root element will be
|
||||
* retrievable.
|
||||
*
|
||||
* @param id
|
||||
* user id to store data under
|
||||
* @param data
|
||||
* xml element with data
|
||||
*/
|
||||
protected void store(String id, Element data) {
|
||||
storage.add(id, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create empty xml element using qualified name
|
||||
*
|
||||
* @param name
|
||||
* @param namespace
|
||||
* @return
|
||||
*/
|
||||
protected static Element createElement(String name, String namespace) {
|
||||
return new DefaultElement(name, new Namespace(null, namespace));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/**
|
||||
* 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.XMPPServer;
|
||||
import org.jivesoftware.openfire.auth.UnauthorizedException;
|
||||
import org.jivesoftware.openfire.pubsub.Node;
|
||||
import org.jivesoftware.openfire.pubsub.PubSubModule;
|
||||
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 handle for dataserver authorization and authentication. Stores client
|
||||
* public keys and authorizes key use for pubsub nodes.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 10, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 11, 2014 2756 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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
|
|
@ -1,23 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<plugin>
|
||||
<class>com.raytheon.openfire.plugin.configuration.collaboration.HttpdCollaborationConfigurationPlugin</class>
|
||||
<name>Httpd Collaboration Configuration</name>
|
||||
<class>com.raytheon.openfire.plugin.configuration.collaboration.HttpConfigurationPlugin</class>
|
||||
<name>Http Collaboration Configuration</name>
|
||||
<description>
|
||||
This plugin will provide httpd collaboration configuration information to CAVE
|
||||
This plugin will provide http collaboration configuration information to CAVE
|
||||
via openfire whenever a user logs in to openfire.
|
||||
</description>
|
||||
<author>bkowal</author>
|
||||
<version>1.0.0</version>
|
||||
<version>2.0.0</version>
|
||||
<date>8/08/2012</date>
|
||||
<minServerVersion>3.7.1</minServerVersion>
|
||||
|
||||
<adminconsole>
|
||||
<tab id="tab-server">
|
||||
<sidebar id="sidebar-server-settings">
|
||||
<id item="httpd-collaboration-monitor-admin" name="Httpd Collaboration Monitor Settings"
|
||||
url="httpd-collaboration-monitor-admin.jsp"
|
||||
description="Click to administer settings for the Httpd Collaboration Monitor." />
|
||||
<id item="http-collaboration-monitor-admin" name="Http Collaboration Monitor Settings"
|
||||
url="http-collaboration-monitor-admin.jsp"
|
||||
description="Click to administer settings for the Http Collaboration Monitor." />
|
||||
</sidebar>
|
||||
</tab>
|
||||
</adminconsole>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
extract dependency information from the plugin manifest.
|
||||
-->
|
||||
<property name="plugin.dependent.libs"
|
||||
value="org.apache.commons.configuration,org.apache.commons.collections,org.apache.http" />
|
||||
value="org.apache.commons.collections,org.apache.http" />
|
||||
|
||||
<import file="${build.dir.location}/${ant.abstract}" />
|
||||
</project>
|
|
@ -1,6 +1,6 @@
|
|||
<%@ page
|
||||
import="org.jivesoftware.openfire.XMPPServer,
|
||||
com.raytheon.openfire.plugin.configuration.collaboration.HttpdCollaborationConfigurationPlugin,
|
||||
com.raytheon.openfire.plugin.configuration.collaboration.HttpConfigurationPlugin,
|
||||
org.jivesoftware.util.ParamUtils,
|
||||
java.util.HashMap,
|
||||
java.util.Map"
|
||||
|
@ -12,31 +12,33 @@
|
|||
<%
|
||||
final long DEFAULT_INTERVAL_S = 60;
|
||||
boolean save = ((request.getParameter("save") == null) == false);
|
||||
|
||||
// Currently, users are not allowed to modify the httpd-collaboration location
|
||||
// because the rpm is not relocatable.
|
||||
long interval = ParamUtils.getLongParameter(request, "txtInterval", DEFAULT_INTERVAL_S);
|
||||
boolean legacy = ParamUtils.getBooleanParameter(request, "chkLegacy", false);
|
||||
String dataserverUsers = ParamUtils.getParameter(request, "txtdataserverUsers", true);
|
||||
if (dataserverUsers == null){
|
||||
dataserverUsers = "";
|
||||
}
|
||||
|
||||
HttpdCollaborationConfigurationPlugin plugin = (HttpdCollaborationConfigurationPlugin) XMPPServer.getInstance().getPluginManager().getPlugin("com.raytheon.openfire.plugin.configuration.collaboration");
|
||||
HttpConfigurationPlugin plugin = (HttpConfigurationPlugin) XMPPServer.getInstance().getPluginManager().getPlugin("com.raytheon.openfire.plugin.configuration.collaboration");
|
||||
|
||||
if (save)
|
||||
{
|
||||
plugin.setHttpdMonitorInterval(interval * 1000);
|
||||
plugin.setHttpMonitorInterval(interval * 1000);
|
||||
plugin.setLegacySupport(legacy);
|
||||
response.sendRedirect("httpd-collaboration-monitor-admin.jsp?settingsSaved=true");
|
||||
plugin.setDataserverUsers(dataserverUsers);
|
||||
response.sendRedirect("http-collaboration-monitor-admin.jsp?settingsSaved=true");
|
||||
return;
|
||||
}
|
||||
|
||||
String location = plugin.getHttpdCollaborationLocation();
|
||||
interval = (plugin.getHttpdMonitorInterval() / 1000);
|
||||
interval = (plugin.getHttpMonitorInterval() / 1000);
|
||||
String legacyChkValue = plugin.hasLegacySupport() ? "checked" : "";
|
||||
dataserverUsers = plugin.getDataserverUsers();
|
||||
%>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Httpd Collaboration Monitor Settings</title>
|
||||
<meta name="pageID" content="httpd-collaboration-monitor-admin" />
|
||||
<title>Http Collaboration Monitor Settings</title>
|
||||
<meta name="pageID" content="http-collaboration-monitor-admin" />
|
||||
|
||||
<script type="text/javascript">
|
||||
function validateInterval()
|
||||
|
@ -73,12 +75,32 @@
|
|||
btnSubmit.disabled = true;
|
||||
}
|
||||
}
|
||||
function validateWhiteList()
|
||||
{
|
||||
var txtdataserverUsers = $('txtdataserverUsers');
|
||||
var spanWhiteListError = $('spanWhiteListError');
|
||||
var btnSubmit = $('btnSubmit');
|
||||
|
||||
var whiteList = txtdataserverUsers.value;
|
||||
|
||||
if (whiteList.match('^[^,@]+@[^,@]+(,[^,@]+@[^,@]+)*$'))
|
||||
{
|
||||
spanWhiteListError.style.display = 'none';
|
||||
btnSubmit.disabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
spanWhiteListError.style.display = 'block';
|
||||
// Disable the submit button
|
||||
btnSubmit.disabled = true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<form action="httpd-collaboration-monitor-admin.jsp?save" method="post">
|
||||
<form name="collabPrefForm" action="http-collaboration-monitor-admin.jsp?save" method="post" onsubmit="return validTest();" >
|
||||
<div class="jive-contentBoxHeader">
|
||||
Httpd Collaboration Monitor Settings
|
||||
Http Collaboration Monitor Settings
|
||||
</div>
|
||||
<div class="jive-contextBox">
|
||||
<% if (ParamUtils.getBooleanParameter(request, "settingsSaved")) { %>
|
||||
|
@ -97,17 +119,11 @@
|
|||
<% } %>
|
||||
|
||||
<p>
|
||||
Set how often (in seconds) the Httpd Collaboration Monitor should verify that the httpd-collaboration process is running.
|
||||
Set how often (in seconds) the Http Collaboration Monitor should verify that the dataserver is online.
|
||||
</p>
|
||||
|
||||
<table cellpadding="3" cellspacing="0" border="0" width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="5%" valign="top">location: </td>
|
||||
<td width="95%">
|
||||
<%= location %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="5%" valign="top">interval: </td>
|
||||
<td width="95%">
|
||||
|
@ -135,6 +151,26 @@
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</br></br></br>
|
||||
<p>
|
||||
HTTP Dataserver users list. User ids that http servers can use to communication with openfire. Comma separated list of full user ids
|
||||
the first id in the list will be used as the primary HTTP Dataserver. Only user ids that are in this list will be allowed to query for session public keys.
|
||||
</p>
|
||||
|
||||
<table cellpadding="3" cellspacing="0" border="0" width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="5%" valign="top">Dataserver User Ids: </td>
|
||||
<td width="95%">
|
||||
<input type="text" id="txtdataserverUsers" name="txtdataserverUsers" onkeyup="validateWhiteList()"
|
||||
value="<%= dataserverUsers %>">
|
||||
<span id="spanWhiteListError" class="jive-error-text" style="display: none;">
|
||||
The white list must be in the form 'user1@hostname,user2@hostname'
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<input id="btnSubmit" type="submit" value="Save Settings" />
|
||||
</form>
|
Loading…
Add table
Reference in a new issue