You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2014/04/25 07:34:03 UTC
[05/51] [partial] BlazeDS Donation from Adobe Systems Inc
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/core/src/flex/messaging/MessageException.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/MessageException.java b/modules/core/src/flex/messaging/MessageException.java
new file mode 100755
index 0000000..f11c59a
--- /dev/null
+++ b/modules/core/src/flex/messaging/MessageException.java
@@ -0,0 +1,443 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging;
+
+import java.util.Map;
+
+import flex.messaging.log.Log;
+import flex.messaging.log.LogCategories;
+import flex.messaging.log.LogEvent;
+import flex.messaging.messages.ErrorMessage;
+import flex.messaging.messages.Message;
+import flex.messaging.util.ExceptionUtil;
+import flex.messaging.util.PropertyStringResourceLoader;
+import flex.messaging.util.ResourceLoader;
+import flex.messaging.util.StringUtils;
+
+/**
+ * The MessageException class is the basic exception type used throughout
+ * the server. This class is extended to support more specific exception types.
+ */
+public class MessageException extends LocalizedException
+{
+ //--------------------------------------------------------------------------
+ //
+ // Static Constants
+ //
+ //--------------------------------------------------------------------------
+
+ // Message exception code strings.
+ public static final String CODE_SERVER_RESOURCE_UNAVAILABLE = "Server.ResourceUnavailable";
+
+ /** @exclude **/
+ static final long serialVersionUID = 3310842114461162689L;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructors
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Default constructor.
+ */
+ public MessageException()
+ {
+ }
+
+ /**
+ * Construct a message specifying a ResourceLoader to be used to load localized strings.
+ *
+ * @param loader
+ */
+ public MessageException(ResourceLoader loader)
+ {
+ super(loader);
+ }
+
+ /**
+ * Constructor with a message.
+ *
+ * @param message The detailed message for the exception.
+ */
+ public MessageException(String message)
+ {
+ setMessage(message);
+ }
+
+ /**
+ * Constructs a new exception with the specified message and the <code>Throwable</code> as the root cause.
+ *
+ * @param message The detailed message for the exception.
+ * @param t The root cause of the exception.
+ */
+ public MessageException(String message, Throwable t)
+ {
+ setMessage(message);
+ setRootCause(t);
+ }
+
+ /**
+ * Constructs a new exception with the specified <code>Throwable</code> as the root cause.
+ *
+ * @param t The root cause of the exception.
+ */
+ public MessageException(Throwable t)
+ {
+ String rootMessage = t.getMessage();
+ if (rootMessage == null)
+ rootMessage = t.toString();
+ setMessage(rootMessage);
+ setRootCause(t);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // code
+ //----------------------------------
+
+ /** @exclude **/
+ protected String code;
+
+ /**
+ * Returns the code of the exception.
+ *
+ * @return Code of the exception.
+ */
+ public String getCode()
+ {
+ return code;
+ }
+
+ /**
+ * Sets the code of the exception.
+ *
+ * @param code Code of the exception.
+ */
+ public void setCode(String code)
+ {
+ this.code = code;
+ }
+
+ //----------------------------------
+ // defaultLogMessageIntro
+ //----------------------------------
+
+ /**
+ * Returns the default initial text for use in the log output generated by <code>logAtHingePoint()</code>.
+ */
+ public String getDefaultLogMessageIntro()
+ {
+ return "Error handling message: ";
+ }
+
+ //----------------------------------
+ // extendedData
+ //----------------------------------
+
+ /** @exclude **/
+ protected Map extendedData;
+
+ /**
+ * Returns the extended data of the exception.
+ *
+ * @return The extended data of the exception.
+ */
+ public Map getExtendedData()
+ {
+ return extendedData;
+ }
+
+ /**
+ * Sets the extended data of the exception.
+ *
+ * @param extendedData The extended data of the exception.
+ */
+ public void setExtendedData(Map extendedData)
+ {
+ this.extendedData = extendedData;
+ }
+
+ //----------------------------------
+ // errorMessage
+ //----------------------------------
+
+ /** @exclude **/
+ protected ErrorMessage errorMessage;
+
+ /**
+ * Returns the error message of the exception.
+ *
+ * @return The error message of the exception.
+ */
+ public ErrorMessage getErrorMessage()
+ {
+ if (errorMessage == null)
+ {
+ errorMessage = createErrorMessage();
+ }
+ return errorMessage;
+ }
+
+ /**
+ * Sets the error message of the exception.
+ *
+ * @param errorMessage The error message of the exception.
+ */
+ public void setErrorMessage(ErrorMessage errorMessage)
+ {
+ this.errorMessage = errorMessage;
+ }
+
+ //----------------------------------
+ // logStackTraceEnabled
+ //----------------------------------
+
+ /**
+ * Indicates whether logging of this exception should include a full stack trace or not.
+ * Default is true.
+ *
+ * @see #logAtHingePoint(Message, ErrorMessage, String)
+ */
+ public boolean isLogStackTraceEnabled()
+ {
+ return true;
+ }
+
+ //----------------------------------
+ // logged
+ //----------------------------------
+
+ protected boolean logged;
+
+ /**
+ * Indicates whether this exception has already been logged
+ * by a call to <code>logAtHingPoint()</code>.
+ * Manual logging for an exception can use <code>setLogged(true)</code>
+ * to suppress any further automatic logging of the exception.
+ *
+ * @return true if the exception has been logged; otherwise false.
+ */
+ public boolean isLogged()
+ {
+ return logged;
+ }
+
+ /**
+ * Records whether this exception has been logged.
+ *
+ * @param value true if the exception has been logged; otherwise false.
+ */
+ public void setLogged(boolean value)
+ {
+ logged = value;
+ }
+
+ //----------------------------------
+ // peferredLogLevel
+ //----------------------------------
+
+ /**
+ * Returns the preferred log level for this exception instance.
+ * The default value is <code>LogEvent.ERROR</code>.
+ *
+ * @see #logAtHingePoint(Message, ErrorMessage, String)
+ */
+ public short getPreferredLogLevel()
+ {
+ return LogEvent.ERROR;
+ }
+
+ //----------------------------------
+ // resourceLoader
+ //----------------------------------
+
+ /**
+ * Returns the <code>ResourceLoader</code> used to load localized strings.
+ *
+ * @return The <code>ResourceLoader</code> used to load localized strings.
+ */
+ @Override protected ResourceLoader getResourceLoader()
+ {
+ if (resourceLoader == null)
+ {
+ try
+ {
+ MessageBroker broker = FlexContext.getMessageBroker();
+ resourceLoader = broker != null? broker.getSystemSettings().getResourceLoader()
+ : new PropertyStringResourceLoader();
+ }
+ catch (NoClassDefFoundError exception) // Could happen in client mode.
+ {
+ return new PropertyStringResourceLoader();
+ }
+ }
+
+ return resourceLoader;
+ }
+
+ //----------------------------------
+ // rootCauseErrorMessage
+ //----------------------------------
+
+ /** @exclude **/
+ public Object getRootCauseErrorMessage()
+ {
+ if (rootCause == null)
+ return null;
+
+ // FIXME: serialize number field.
+ return rootCause instanceof MessageException?
+ ((MessageException)rootCause).createErrorMessage() : rootCause;
+ }
+
+ //----------------------------------
+ // statusCode
+ //----------------------------------
+
+ protected int statusCode;
+
+ /**
+ * Returns the HTTP status code of the exception.
+ *
+ * @return The HTTP status code of the exception.
+ */
+ public int getStatusCode()
+ {
+ return statusCode;
+ }
+
+ /**
+ * Sets the HTTP status code of the exception.
+ *
+ * @param statusCode The HTTP status code of the exception.
+ */
+ public void setStatusCode(int statusCode)
+ {
+ this.statusCode = statusCode;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Public Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Creates an error message from the exception.
+ *
+ * @return The error message.
+ */
+ public ErrorMessage createErrorMessage()
+ {
+ ErrorMessage msg = new ErrorMessage();
+ msg.faultCode = code != null? code : "Server.Processing";
+ msg.faultString = message;
+ msg.faultDetail = details;
+ msg.rootCause = getRootCauseErrorMessage();
+ if (extendedData != null)
+ msg.extendedData = extendedData;
+ if (statusCode != 0)
+ msg.setHeader(Message.STATUS_CODE_HEADER, statusCode);
+ return msg;
+ }
+
+ /**
+ * Invoked at hinge-points in server processing where catch-all exception logging is performed.
+ * This method uses <code>isLogged()</code> and <code>setLogged()</code> to avoid repeat logging
+ * of the same exception and uses <code>getPreferredLogLevel()</code> which may be
+ * overridden in subclasses to control the log level that the logging is output at.
+ * The underlying exception stack traces are also conditionally included in log output
+ * if the exception class allows it and this is determined by invoking <code>isLogStackTraceEnabled()</code>
+ *
+ * @param inboundMessage The inbound message that triggered an exception during processing.
+ * @param outboundMessage The outbound <code>ErrorMessage</code>, which may be null depending on whether it has been generated
+ * or not at the point this method is invoked.
+ * @param logMessageIntro The beginning text for the log message, which may be null; default value is returned by <code>getDefaultLogMessageIntro()</code>.
+ */
+ public void logAtHingePoint(Message inboundMessage, ErrorMessage outboundMessage, String logMessageIntro)
+ {
+ if (!isLogged())
+ {
+ setLogged(true);
+
+ short preferredLevel = getPreferredLogLevel();
+ // If the preferred level is less than the current Log level; return early.
+ if (preferredLevel < Log.getTargetLevel())
+ return;
+
+ // Construct core log output.
+ StringBuffer output = new StringBuffer();
+ output.append((logMessageIntro != null) ? logMessageIntro : getDefaultLogMessageIntro());
+ output.append(this.toString());
+ output.append(StringUtils.NEWLINE);
+ output.append(" incomingMessage: ");
+ output.append(inboundMessage);
+ output.append(StringUtils.NEWLINE);
+ if (outboundMessage != null)
+ {
+ output.append(" errorReply: ");
+ output.append(outboundMessage);
+ output.append(StringUtils.NEWLINE);
+ }
+ if (isLogStackTraceEnabled())
+ {
+ output.append(ExceptionUtil.exceptionFollowedByRootCausesToString(this));
+ output.append(StringUtils.NEWLINE);
+ }
+
+ switch (preferredLevel)
+ {
+ case LogEvent.FATAL:
+ {
+ Log.getLogger(LogCategories.MESSAGE_GENERAL).fatal(output.toString());
+ break;
+ }
+ case LogEvent.ERROR:
+ {
+ Log.getLogger(LogCategories.MESSAGE_GENERAL).error(output.toString());
+ break;
+ }
+ case LogEvent.WARN:
+ {
+ Log.getLogger(LogCategories.MESSAGE_GENERAL).warn(output.toString());
+ break;
+ }
+ case LogEvent.INFO:
+ {
+ Log.getLogger(LogCategories.MESSAGE_GENERAL).info(output.toString());
+ break;
+ }
+ case LogEvent.DEBUG:
+ {
+ Log.getLogger(LogCategories.MESSAGE_GENERAL).debug(output.toString());
+ break;
+ }
+ default:
+ {
+ Log.getLogger(LogCategories.MESSAGE_GENERAL).fatal("Failed to log exception for handling message due to an invalid preferred log level: " + preferredLevel);
+ break;
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/core/src/flex/messaging/MessageRoutedEvent.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/MessageRoutedEvent.java b/modules/core/src/flex/messaging/MessageRoutedEvent.java
new file mode 100755
index 0000000..2cf0628
--- /dev/null
+++ b/modules/core/src/flex/messaging/MessageRoutedEvent.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging;
+
+import flex.messaging.messages.Message;
+
+import java.util.EventObject;
+
+/**
+ * @exclude
+ * This event indicates that the source message has been routed to the outbound message queues
+ * for all target clients.
+ * This can be used as the trigger for performing optimized IO to flush these queued messages to
+ * remote hosts over the network.
+ */
+public class MessageRoutedEvent extends EventObject
+{
+ /**
+ * @exclude
+ */
+ private static final long serialVersionUID = -3063794416424805005L;
+
+ /**
+ * Constructs a new <tt>MessageRoutedEvent</tt> using the supplied source <tt>Message</tt>.
+ *
+ * @param message The message that has been routed.
+ */
+ public MessageRoutedEvent(Message message)
+ {
+ super(message);
+ }
+
+ /**
+ * Returns the message that has been routed.
+ */
+ public Message getMessage()
+ {
+ return (Message)getSource();
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/core/src/flex/messaging/MessageRoutedListener.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/MessageRoutedListener.java b/modules/core/src/flex/messaging/MessageRoutedListener.java
new file mode 100755
index 0000000..4a04267
--- /dev/null
+++ b/modules/core/src/flex/messaging/MessageRoutedListener.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging;
+
+import java.util.EventListener;
+
+/**
+ * @exclude
+ * Provides notification for multicast message routing events to support optimized
+ * asynchronous IO to the target remote hosts.
+ */
+public interface MessageRoutedListener extends EventListener
+{
+ /**
+ * Invoked when a message has been routed to the outbound queues for all target
+ * clients.
+ *
+ * @param event The event containing the source message.
+ */
+ void messageRouted(MessageRoutedEvent event);
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/core/src/flex/messaging/MessageRoutedNotifier.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/MessageRoutedNotifier.java b/modules/core/src/flex/messaging/MessageRoutedNotifier.java
new file mode 100755
index 0000000..c2107ba
--- /dev/null
+++ b/modules/core/src/flex/messaging/MessageRoutedNotifier.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging;
+
+import flex.messaging.messages.Message;
+
+import java.util.ArrayList;
+
+/**
+ * @exclude
+ * Supports registration and notification of <tt>MessageRoutedListener</tt>s.
+ * An instance of this class is exposed by <tt>FlexContext</tt> while a message is
+ * being routed, and once routing of the message to the outbound messages queues for
+ * target clients and registered listeners are notified.
+ * This class performs no synchronization because it is only used within the context
+ * of a single Thread, and only during the routing of a single message.
+ */
+public class MessageRoutedNotifier
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructs a <tt>MessageRoutedNotifier</tt> for the supplied source message.
+ *
+ * @param The source message being routed.
+ */
+ public MessageRoutedNotifier(Message message)
+ {
+ this.message = message;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * The source message being routed.
+ */
+ private final Message message;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // messageRoutedListeners
+ //----------------------------------
+
+ private ArrayList listeners;
+
+ /**
+ * Adds a <tt>MessageRoutedListener</tt>.
+ */
+ public void addMessageRoutedListener(MessageRoutedListener listener)
+ {
+ if (listener != null)
+ {
+ // Lazy-init only if necessary.
+ if (listeners == null)
+ listeners = new ArrayList();
+
+ // Add if absent.
+ if (!listeners.contains(listener))
+ listeners.add(listener);
+ }
+ }
+
+ /**
+ * Removes a <tt>MessageRoutedListener</tt>.
+ */
+ public void removeMessageRoutedListener(MessageRoutedListener listener)
+ {
+ if ((listener != null) && (listeners != null))
+ listeners.remove(listener);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Public Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Notifies registered listeners of a routed message.
+ *
+ * @param message The message that has been routed.
+ */
+ public void notifyMessageRouted()
+ {
+ if ((listeners != null) && !listeners.isEmpty())
+ {
+ MessageRoutedEvent event = new MessageRoutedEvent(message);
+ int n = listeners.size();
+ for (int i = 0; i < n; ++i)
+ ((MessageRoutedListener)listeners.get(i)).messageRouted(event);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/core/src/flex/messaging/Server.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/Server.java b/modules/core/src/flex/messaging/Server.java
new file mode 100755
index 0000000..3022fe6
--- /dev/null
+++ b/modules/core/src/flex/messaging/Server.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging;
+
+/**
+ * The interface for a shared server instance that may be associated with a
+ * <tt>MessageBroker</tt> and used by endpoints.
+ */
+public interface Server extends FlexComponent
+{
+ /**
+ * Returns the id for the server.
+ * Endpoints can lookup server instances that have been associated with a <tt>MessageBroker</tt> using {@link MessageBroker#getServer(String)}.
+ */
+ String getId();
+
+ /**
+ * Sets the id for the server.
+ */
+ void setId(String value);
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/core/src/flex/messaging/ServiceValidationListener.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/ServiceValidationListener.java b/modules/core/src/flex/messaging/ServiceValidationListener.java
new file mode 100755
index 0000000..4cecbd7
--- /dev/null
+++ b/modules/core/src/flex/messaging/ServiceValidationListener.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging;
+
+/**
+ * @exclude
+ */
+public interface ServiceValidationListener
+{
+ /**
+ * This method gets called before any other processing of the describeServices method.
+ * It allows a hook for external systems that need to update the service destinations at runtime.
+ */
+ void validateServices();
+ void validateDestination(String destination);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/core/src/flex/messaging/VersionInfo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/VersionInfo.java b/modules/core/src/flex/messaging/VersionInfo.java
new file mode 100755
index 0000000..4ff2cc6
--- /dev/null
+++ b/modules/core/src/flex/messaging/VersionInfo.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging;
+
+import flex.messaging.util.StringUtils;
+
+
+/**
+ * Class representing the build version of Data Services.
+ *
+ *@exclude
+ */
+public class VersionInfo
+{
+ //Cache this info as it should not change during the time class is loaded
+ public static String BUILD_MESSAGE;
+ public static String BUILD_NUMBER_STRING;
+ public static String BUILD_TITLE;
+ public static long BUILD_NUMBER;
+
+ private static final String LCDS_CLASS = "flex.data.DataService";
+
+ public static String buildMessage()
+ {
+ if (BUILD_MESSAGE == null)
+ {
+ try
+ {
+ //Ensure we've parsed build info
+ getBuild();
+
+ if (StringUtils.isEmpty(BUILD_NUMBER_STRING))
+ {
+ BUILD_MESSAGE = BUILD_TITLE;
+ }
+ else
+ {
+ BUILD_MESSAGE = BUILD_TITLE + ": " + BUILD_NUMBER_STRING;
+ }
+ }
+ catch (Throwable t)
+ {
+ BUILD_MESSAGE = BUILD_TITLE +": information unavailable";
+ }
+ }
+
+ return BUILD_MESSAGE;
+ }
+
+ public static long getBuildAsLong()
+ {
+ if (BUILD_NUMBER == 0)
+ {
+ getBuild();
+
+ if (BUILD_NUMBER_STRING != null && !BUILD_NUMBER_STRING.equals(""))
+ {
+ try
+ {
+ BUILD_NUMBER = Long.parseLong(BUILD_NUMBER_STRING);
+ }
+ catch (NumberFormatException nfe)
+ {
+ // ignore, just return 0
+ }
+ }
+ }
+
+ return BUILD_NUMBER;
+ }
+
+ public static String getBuild()
+ {
+ if (BUILD_NUMBER_STRING == null)
+ {
+ Class classToUseForManifest;
+
+ try
+ {
+ classToUseForManifest = Class.forName(LCDS_CLASS);
+ }
+ catch (ClassNotFoundException e)
+ {
+ classToUseForManifest = VersionInfo.class;
+ }
+
+ try
+ {
+ BUILD_NUMBER_STRING = "";
+ Package pack = classToUseForManifest.getPackage();
+ BUILD_NUMBER_STRING = pack.getImplementationVersion();
+ BUILD_TITLE = pack.getImplementationTitle();
+ }
+ catch (Throwable t)
+ {
+ // ignore, just return empty string
+ }
+ }
+
+ return BUILD_NUMBER_STRING;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/core/src/flex/messaging/client/AsyncPollHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/client/AsyncPollHandler.java b/modules/core/src/flex/messaging/client/AsyncPollHandler.java
new file mode 100755
index 0000000..64573e3
--- /dev/null
+++ b/modules/core/src/flex/messaging/client/AsyncPollHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging.client;
+
+/**
+ * Defines the interface to handle asynchronous poll results.
+ */
+public interface AsyncPollHandler
+{
+ /**
+ * Invoked by the <tt>FlexClient</tt> when an asynchronous poll result is available.
+ *
+ * @param flushResult The flush result containing messages to return in the poll response and
+ * an optional wait time before the client should issue its next poll.
+ */
+ void asyncPollComplete(FlushResult flushResult);
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/core/src/flex/messaging/client/EndpointPushHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/client/EndpointPushHandler.java b/modules/core/src/flex/messaging/client/EndpointPushHandler.java
new file mode 100755
index 0000000..a043cb7
--- /dev/null
+++ b/modules/core/src/flex/messaging/client/EndpointPushHandler.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging.client;
+
+import java.util.List;
+
+import flex.messaging.MessageClient;
+import flex.messaging.messages.Message;
+
+/**
+ * Defines the interface for a handler that may be registered by an endpoint with a <tt>FlexClient</tt> in order
+ * to push messages to a connected client.
+ */
+public interface EndpointPushHandler
+{
+ /**
+ * Invoked to shut down the handler.
+ * It may be invoked by the endpoint when the underlying connection it manages to the client closes,
+ * or by the <tt>FlexClient</tt> if it is invalidated.
+ * The implementation of this method should release any resources, and should not attempt to notify the
+ * client of an explicit disconnect.
+ *
+ * @see #close(boolean)
+ */
+ void close();
+
+ /**
+ * Invoked to shut down the handler.
+ * It may be invoked by the endpoint when the underlying connection it manages to the client closes,
+ * or by the <tt>FlexClient</tt> if it is invalidated.
+ * The implementation of this method should release any resources, and may attempt to notify the client
+ * Channel that it has been disconnected in order to suppress automatic reconnect behavior.
+ *
+ * @param disconnectChannel True to attempt to notify the client of an explicit disconnect in order to
+ * suppress automatic reconnect behavior.
+ */
+ void close(boolean disconnectChannel);
+
+ /**
+ * Invoked by the <tt>FlexClient</tt> when it has messages to push to
+ * the client.
+ *
+ * @param messagesToPush The list of messages to push.
+ */
+ void pushMessages(List<Message> messagesToPush);
+
+ /**
+ * Invoked to notify the handler that the <tt>MessageClient</tt> subscription is using this handler.
+ * If subscriptions should be invalidated if the handler is closed, it should retain references to
+ * all registered <tt>MessageClient</tt> instances and invalidate them when it closes.
+ *
+ * @param messageClient The <tt>MessageClient</tt> subscription using this handler.
+ */
+ void registerMessageClient(MessageClient messageClient);
+
+ /**
+ * Invoked to notify the handler that a <tt>MessageClient</tt> subscription that was using it has
+ * been invalidated.
+ * If the handler is tracking the set of <tt>MessageClient</tt> instances that are using it, the handler should
+ * remove the instance from its set.
+ *
+ * @param messageClient The <tt>MessageClient</tt> subscription no longer using this handler.
+ */
+ void unregisterMessageClient(MessageClient messageClient);
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/core/src/flex/messaging/client/EndpointPushNotifier.java
----------------------------------------------------------------------
diff --git a/modules/core/src/flex/messaging/client/EndpointPushNotifier.java b/modules/core/src/flex/messaging/client/EndpointPushNotifier.java
new file mode 100755
index 0000000..925f7e1
--- /dev/null
+++ b/modules/core/src/flex/messaging/client/EndpointPushNotifier.java
@@ -0,0 +1,461 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package flex.messaging.client;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import flex.messaging.FlexContext;
+import flex.messaging.FlexSession;
+import flex.messaging.FlexSessionListener;
+import flex.messaging.MessageClient;
+import flex.messaging.MessageClientListener;
+import flex.messaging.endpoints.BaseStreamingHTTPEndpoint;
+import flex.messaging.endpoints.Endpoint;
+import flex.messaging.log.Log;
+import flex.messaging.log.LogCategories;
+import flex.messaging.messages.AsyncMessage;
+import flex.messaging.messages.CommandMessage;
+import flex.messaging.util.TimeoutAbstractObject;
+import flex.messaging.util.UUIDUtils;
+
+/**
+ * @exclude
+ * Instances of this class are used by endpoints that support streaming
+ * outbound data to connected clients when the client is not polling and
+ * the FlexSession representing the connection does not support push directly.
+ * This generally requires that the client and endpoint establish a separate,
+ * physical connection for pushed data that is part of a larger, logical
+ * connection/session.
+ * <p>
+ * When the endpoint establishes this physical streaming connection it will
+ * create an instance of this class, register it with the FlexClient and then
+ * wait on the public <code>pushNeeded</code> condition variable.
+ * When data arrives to push to the remote client, the FlexClient will queue it
+ * with this notifier instance and the waiting endpoint will be notified.
+ * The endpoint will retrieve the queued messages from the notifier instance and will
+ * stream them to the client and then go back into a wait state on the
+ * <code>pushNeeded</code> condition variable.
+ * </p><p>
+ * Note that this implementation is based upon <code>Object.wait()</code>; it is not a
+ * non-blocking implementation.
+ * </p>
+ */
+public class EndpointPushNotifier extends TimeoutAbstractObject implements EndpointPushHandler, FlexSessionListener, MessageClientListener
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructs a PushNotifier instance.
+ *
+ * @param endpoint The endpoint that will use this notifier.
+ * @param flexClient The FlexClient that will use this notifier.
+ */
+ public EndpointPushNotifier(Endpoint endpoint, FlexClient flexClient)
+ {
+ notifierId = UUIDUtils.createUUID(false /* doesn't need to be secure */);
+ this.endpoint = endpoint;
+ this.flexClient = flexClient;
+ flexClient.registerEndpointPushHandler(this, endpoint.getId());
+ flexSession = FlexContext.getFlexSession();
+ if (flexSession != null)
+ flexSession.addSessionDestroyedListener(this);
+ invalidateMessageClientOnStreamingClose = (endpoint instanceof BaseStreamingHTTPEndpoint)?
+ ((BaseStreamingHTTPEndpoint)endpoint).isInvalidateMessageClientOnStreamingClose() : false;
+ updateLastUse(); // Initialize last use timestamp to construct time.
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Public Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * The condition variable that the endpoint waits on for pushed data to arrive.
+ */
+ public final Object pushNeeded = new Object();
+
+ //--------------------------------------------------------------------------
+ //
+ // Private Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Flag indicating whether the notifier has been closed/shut down.
+ * This is used to signal a waiting endpoint that it should break out of its
+ * wait loop and close its streaming connection.
+ */
+ private volatile boolean closed;
+
+ /**
+ * Flag indicating that the notifier has started closing; used to allow only
+ * one thread to execute the close() logic and delay flipping closed to true
+ * to allow any final messages to be streamed to the client before the endpoint
+ * using the notifier breaks out of its wait/notify loop and terminates the
+ * streaming connection.
+ */
+ private volatile boolean closing;
+
+ /**
+ * The number of minutes a client can remain idle before the server
+ * times the notifier out.
+ */
+ private int idleTimeoutMinutes;
+
+ /**
+ * Whether to invalidate the message-client when the streaming connection is closed.
+ */
+ private final boolean invalidateMessageClientOnStreamingClose;
+
+ /**
+ * The endpoint that uses this notifier.
+ */
+ private final Endpoint endpoint;
+
+ /**
+ * The FlexClient this notifier is associated with.
+ */
+ private final FlexClient flexClient;
+
+ /**
+ * The FlexSession this notifier is associated with.
+ */
+ private final FlexSession flexSession;
+
+ /**
+ * Lock for instance-level synchronization.
+ */
+ private final Object lock = new Object();
+
+ /**
+ * Log category used by the notifier. Initialized to ENDPOINT_GENERAL but
+ * endpoints using this notifier should set it to their own log categories.
+ */
+ private String logCategory = LogCategories.ENDPOINT_GENERAL;
+
+ /**
+ * Queue of messages that the FlexClient will populate and the endpoint will drain to
+ * stream to the client.
+ */
+ private List<AsyncMessage> messages;
+
+ /**
+ * List of MessageClient subscriptions using this endpoint push notifier.
+ * When this notifier is closed, any associated subscriptions need to be invalidated.
+ */
+ private final CopyOnWriteArrayList<MessageClient> messageClients = new CopyOnWriteArrayList<MessageClient>();
+
+ /**
+ * Unique identifier for this instance.
+ */
+ private final String notifierId;
+
+ //--------------------------------------------------------------------------
+ //
+ // Public Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Moves this notifier to a closed state, notifying any listeners,
+ * associated subscriptions and waiting endpoints.
+ * Does not attempt to notify the client Channel of the disconnect thereby allowing
+ * automatic reconnect processing to run.
+ */
+ public void close()
+ {
+ close(false);
+ }
+
+ /**
+ * Moves this notifier to a closed state, notifying any listeners,
+ * associated subscriptions and waiting endpoints.
+ * Attempts to notify the client Channel of an explicit disconnect, thereby suppressing
+ * automatic reconnect processing.
+ *
+ * @param disconnectChannel True to attempt to notify the client Channel of the disconnect
+ * and suppress automatic reconnect processing.
+ */
+ public void close(boolean disconnectChannel)
+ {
+ synchronized (lock)
+ {
+ if (closed || closing)
+ return;
+
+ closing = true;
+ }
+
+ cancelTimeout();
+
+ if (flexSession != null)
+ flexSession.removeSessionDestroyedListener(this);
+
+ // Shut down flow of further messages to this notifier.
+ flexClient.unregisterEndpointPushHandler(this, endpoint.getId());
+
+ // Push a disconnect command down to the client to suppress automatic reconnect.
+ if (disconnectChannel)
+ {
+ ArrayList<AsyncMessage> list = new ArrayList<AsyncMessage>(1);
+ CommandMessage disconnect = new CommandMessage(CommandMessage.DISCONNECT_OPERATION);
+ list.add(disconnect);
+ pushMessages(list);
+ }
+
+ // Invalidate associated subscriptions; this doesn't attempt to notify the client.
+ // Any client subscriptions made over this endpoint will be automatically invalidated
+ // on the client when it receives its channel disconnect event.
+ if (invalidateMessageClientOnStreamingClose)
+ {
+ for (Iterator<MessageClient> iter = messageClients.iterator() ; iter.hasNext();)
+ iter.next().invalidate();
+ }
+
+ // Move to final closed state; after this we need to notify one last time to stream
+ // any final messages to the client and allow the endpoint to shut down its streaming
+ // connection.
+ synchronized (lock)
+ {
+ closed = true;
+ closing = false;
+ }
+ synchronized (pushNeeded)
+ {
+ pushNeeded.notifyAll();
+ }
+ }
+
+ /**
+ * Returns any messages available to push to the client, and removes them
+ * from this notifier.
+ * Notified endpoints should invoke this method to retrieve messages, stream them
+ * to the client and then re-enter the wait state.
+ * This method acquires a lock on <code>pushNeeded</code>.
+ *
+ * @return The messages to push to the client.
+ */
+ public List<AsyncMessage> drainMessages()
+ {
+ synchronized (pushNeeded)
+ {
+ List<AsyncMessage> messagesToPush = messages;
+ messages = null;
+ return messagesToPush;
+ }
+ }
+
+ /**
+ * Returns whether the notifier has closed; used to break the endpoint's wait cycle.
+ *
+ * @return True if the notifier has closed; otherwise false.
+ */
+ public boolean isClosed()
+ {
+ return closed;
+ }
+
+ /**
+ * Returns the endpoint that is using this notifier.
+ *
+ * @return The endpoint using this notifier.
+ */
+ public Endpoint getEndpoint()
+ {
+ return endpoint;
+ }
+
+ /**
+ * Returns the idle timeout minutes used by the notifier.
+ *
+ * @return The idle timeout minutes used by the notifier.
+ */
+ public int getIdleTimeoutMinutes()
+ {
+ return idleTimeoutMinutes;
+ }
+
+ /**
+ * Sets the idle timeout minutes used by the notifier.
+ *
+ * @param idleTimeoutMinutes The idle timeout minutes used by the notifier.
+ */
+ public void setIdleTimeoutMinutes(int idleTimeoutMinutes)
+ {
+ this.idleTimeoutMinutes = idleTimeoutMinutes;
+ }
+
+ /**
+ * Returns the log category used by this notifier.
+ *
+ * @return The log category used by this notifier.
+ */
+ public String getLogCategory()
+ {
+ return logCategory;
+ }
+
+ /**
+ * Sets the log category used by this notifier. Endpoints using this notifier
+ * should set it to their own log categories.
+ *
+ * @param logCategory The log category for the notifier to use.
+ */
+ public void setLogCategory(String logCategory)
+ {
+ this.logCategory = logCategory;
+ }
+
+ /**
+ * Returns the unique id for this notifier.
+ *
+ * @return The unique id for this notifier.
+ */
+ public String getNotifierId()
+ {
+ return notifierId;
+ }
+
+ /**
+ * @exclude
+ * Implements TimeoutCapable.
+ * Determine the time, in milliseconds, that this object is allowed to idle
+ * before having its timeout method invoked.
+ */
+ public long getTimeoutPeriod()
+ {
+ return (idleTimeoutMinutes * 60 * 1000);
+ }
+
+ /**
+ * @exclude
+ */
+ public void messageClientCreated(MessageClient messageClient)
+ {
+ // No-op.
+ }
+
+ /**
+ * @exclude
+ */
+ public void messageClientDestroyed(MessageClient messageClient)
+ {
+ unregisterMessageClient(messageClient);
+ }
+
+ /**
+ * Used by FlexClient to push messages to the endpoint.
+ * This method will automatically notify a waiting endpoint, if one exists
+ * and it acquires a lock on <code>pushNeeded</code>.
+ *
+ * @param messages The messages to push to the client.
+ */
+ public void pushMessages(List messagesToPush)
+ {
+ if (!messagesToPush.isEmpty())
+ {
+ synchronized (pushNeeded)
+ {
+ // Push these straight on through; notify immediately.
+ if (messages == null)
+ messages = messagesToPush;
+ else
+ messages.addAll(messagesToPush);
+
+ // If the notifier isn't closing, notify; otherwise just add and the close will
+ // notify once it completes.
+ if (!closing)
+ pushNeeded.notifyAll();
+ }
+ }
+ }
+
+ /**
+ * Registers a MessageClient subscription that depends on this notifier.
+ *
+ * @param messageClient A MessageClient that depends on this notifier.
+ */
+ public void registerMessageClient(MessageClient messageClient)
+ {
+ if (messageClient != null)
+ {
+ if (messageClients.addIfAbsent(messageClient))
+ messageClient.addMessageClientDestroyedListener(this);
+ }
+ }
+
+ /**
+ * Handle session creation events. This handler is a no-op because the notifier
+ * is only concerned with its associated session's destruction.
+ *
+ * @param flexSession The newly created FlexSession.
+ */
+ public void sessionCreated(FlexSession flexSession)
+ {
+ // No-op.
+ }
+
+ /**
+ * Handle session destruction events. This will be invoked when the notifier's
+ * associated session is invalidated, and this will trigger the notifier to close.
+ *
+ * @param flexSession The FlexSession being invalidated.
+ */
+ public void sessionDestroyed(FlexSession flexSession)
+ {
+ if (Log.isInfo())
+ Log.getLogger(logCategory).info("Endpoint with id '" + endpoint.getId() + "' is closing"
+ + " a streaming connection for the FlexClient with id '" + flexClient.getId() + "'"
+ + " since its associated session has been destroyed.");
+ close(true /* disconnect client Channel */);
+ }
+
+ /**
+ * @exclude
+ * Implements TimeoutCapable.
+ * Inform the object that it has timed out.
+ */
+ public void timeout()
+ {
+ if (Log.isInfo())
+ Log.getLogger(logCategory).info("Endpoint with id '" + endpoint.getId() + "' is timing out"
+ + " a streaming connection for the FlexClient with id '" + flexClient.getId() + "'");
+ close(true /* disconnect client Channel */);
+ }
+
+ /**
+ * Unregisters a MessageClient subscription that depended on this notifier.
+ *
+ * @param messageClient A MessageClient that depended on this notifier.
+ */
+ public void unregisterMessageClient(MessageClient messageClient)
+ {
+ if (messageClient != null)
+ {
+ messageClient.removeMessageClientDestroyedListener(this);
+ messageClients.remove(messageClient);
+ }
+ }
+}
\ No newline at end of file