blob: 7a505a03f2a29bec4fdfa3a9f370bb6b2d187f4e [file] [log] [blame]
/*
* 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.io;
import flex.messaging.FlexContext;
import flex.messaging.MessageBroker;
import flex.messaging.io.amf.ASObject;
import flex.messaging.io.amf.translator.ASTranslator;
import java.util.IdentityHashMap;
import java.util.Map;
/**
* A simple context to hold type marshalling specific settings.
*/
public class TypeMarshallingContext
{
private static ThreadLocal<TypeMarshallingContext> contexts = new ThreadLocal<TypeMarshallingContext>();
private static ThreadLocal<TypeMarshaller> marshallers = new ThreadLocal<TypeMarshaller>();
private IdentityHashMap knownObjects;
private ClassLoader classLoader;
/**
* Constructs a default type marshalling context.
*/
public TypeMarshallingContext()
{
}
/**
* Establishes a TypeMarshallingContext for the current thread.
* Users are not expected to call this function.
* @param context The current TypeMarshallingContext.
*/
public static void setTypeMarshallingContext(TypeMarshallingContext context)
{
if (context == null)
contexts.remove();
else
contexts.set(context);
}
/**
* Get current TypeMarshallingContext object
* @return The current thread's TypeMarshallingContext.
*/
public static TypeMarshallingContext getTypeMarshallingContext()
{
TypeMarshallingContext context = contexts.get();
if (context == null)
{
context = new TypeMarshallingContext();
TypeMarshallingContext.setTypeMarshallingContext(context);
}
return context;
}
/**
* Establishes a TypeMarshallingContext for the current thread.
* Users are not expected to call this function.
*
* @param marshaller The current TypeMarshaller.
*/
public static void setTypeMarshaller(TypeMarshaller marshaller)
{
if (marshaller == null)
marshallers.remove();
else
marshallers.set(marshaller);
}
/**
* Get current TypeMarshaller.
* @return The current thread's TypeMarshaller.
*/
public static TypeMarshaller getTypeMarshaller()
{
TypeMarshaller marshaller = marshallers.get();
if (marshaller == null)
{
marshaller = new ASTranslator();
setTypeMarshaller(marshaller);
}
return marshaller;
}
/**
* Returns the custom ClassLoader for this type marshalling session, or
* defaults to the current MessageBroker's ClassLoader if none has been set.
* @return ClassLoader the ClassLoader in use
*/
public ClassLoader getClassLoader()
{
if (classLoader != null)
return classLoader;
try
{
MessageBroker messageBroker = FlexContext.getMessageBroker();
return messageBroker != null? messageBroker.getClassLoader() : null;
}
catch (NoClassDefFoundError exception) // Could happen in client mode.
{
return null;
}
}
/**
* Sets a custom classloader for this type marshalling session that will
* be used to create new instances of strongly typed objects.
* @param loader the ClassLoader to use
*/
public void setClassLoader(ClassLoader loader)
{
classLoader = loader;
}
/**
* A map of known objects already encountered in this type marshalling
* session.
* @return IdentityHashMap the known objects
*/
public IdentityHashMap getKnownObjects()
{
if (knownObjects == null)
knownObjects = new IdentityHashMap(64);
return knownObjects;
}
/**
* Sets the list of the objects already encountered for this type
* marshalling session.
* @param knownObjects the IdentityHashMap object
*/
public void setKnownObjects(IdentityHashMap knownObjects)
{
this.knownObjects = knownObjects;
}
/**
* Resets the list of known objects.
*/
public void reset()
{
if (knownObjects != null)
knownObjects.clear();
}
/**
* A utility method to determine whether an anonymous type specifies
* a strong type name, such as ASObject.getType() or the legacy Flash
* Remoting convention of using a _remoteClass property.
* @param obj the object to check
* @return The name of the strong type, or null if none was specified.
*/
public static String getType(Object obj)
{
String type = null;
if (obj != null && obj instanceof Map)
{
Map map = (Map)obj;
//Check for an Object.registerClass Typed ASObject
if (map instanceof ASObject)
{
ASObject aso = (ASObject)map;
type = aso.getType();
}
SerializationContext sc = SerializationContext.getSerializationContext();
if (type == null && sc.supportRemoteClass)
{
Object registerClass = map.get(MessageIOConstants.REMOTE_CLASS_FIELD);
if (registerClass != null && registerClass instanceof String)
{
type = (String)registerClass;
}
}
}
return type;
}
/**
* Clears out the thread local state after the request completes.
*/
public static void clearThreadLocalObjects()
{
if (contexts != null)
{
contexts.remove();
}
if (marshallers != null)
{
marshallers.remove();
}
}
/**
*
* Destroy static thread local storage.
* Call ONLY on shutdown.
*/
public static void releaseThreadLocalObjects()
{
clearThreadLocalObjects();
contexts = null;
marshallers = null;
}
/**
*
* Create static thread local storage.
*/
public static void createThreadLocalObjects()
{
if (contexts == null)
contexts = new ThreadLocal();
if (marshallers == null)
marshallers = new ThreadLocal();
}
}