/*=============================================================================*
* Copyright 2006 The Apache Software Foundation
*
* Licensed 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 org.apache.muse.core.platform;
import java.util.Collection;
import java.util.Iterator;
import org.w3c.dom.Document;
import org.apache.muse.core.Environment;
import org.apache.muse.core.descriptor.DeploymentDescriptor;
import org.apache.muse.core.descriptor.DescriptorConstants;
import org.apache.muse.core.descriptor.RouterDefinition;
import org.apache.muse.core.descriptor.SerializerDefinition;
import org.apache.muse.core.descriptor.SimpleDeploymentDescriptor;
import org.apache.muse.core.routing.ResourceRouter;
import org.apache.muse.core.serializer.ArraySerializer;
import org.apache.muse.core.serializer.Serializer;
import org.apache.muse.core.serializer.SerializerRegistry;
import org.apache.muse.util.ReflectUtils;
import org.apache.muse.ws.addressing.soap.SoapFault;
import org.apache.muse.ws.addressing.soap.SoapUtils;
/**
*
* This class provides all of the generic initialization and shutdown
* routines without referencing any specific implementation of the
* various sub-components (ResourceRouter, Environment, etc.). It allows
* implementers of concrete classes to focus on the platform-specific
* request handling method(s) they need and to provide the implementation
* classes of the various sub-components without having to code the
* initialization logic and interactions between them.
*
* @author Dan Jemiolo (danj)
*
*/
public abstract class AbstractIsolationLayer implements IsolationLayer
{
//
// True if the service has been invoked at least once. This field is
// NOT synchronized because it will only be modified once (the first
// time the service is used); all subsequent requests will read this
// value to confirm that no initialization is needed.
//
private static boolean _hasBeenInitialized = false;
//
// True if the intialization of the application failed and no SOAP
// requests should be handled. This is useful for concrete isolation
// layers that fit into other programming models that break up the
// initialization and request handling events into disparate components.
//
private static boolean _hasFailedToInitialize = false;
//
// This value is set if initialization fails but we can't report it
// until later on
//
private static SoapFault _causeOfFailure = null;
//
// This flag allows us to "synchronize" initialization and prevent
// infinite recursion if the initialization of a resource results
// in SOAP requests to other resources deployed in the the same app
//
private static boolean _isInitializing = false;
private static boolean _hasBeenShutdown = false;
//
// The object that implements all of the service's operations. This
// is the outer-most layer of the user's code, where SOAP messages
// are transformed into POJOs and actual implementations invoked.
//
private static ResourceRouter _router = null;
/**
*
* This method can be overridden to provide a different deployment
* descriptor parser implementation.
*
* @return An instance of SimpleDeploymentDescriptor
*
*/
protected DeploymentDescriptor createDeploymentDescriptor()
{
return new SimpleDeploymentDescriptor();
}
/**
*
* @return A concrete instance of the Environment class, specific to
* the deployment platform.
*
* @see Environment
*
*/
protected abstract Environment createEnvironment();
public ResourceRouter getRouter()
{
return _router;
}
public void initialize()
{
//
// this flag is never modified anywhere else, so we can read it
// w/o worrying about race conditions
//
// NOTE: we set the flag here so that if the router's initialize()
// makes remote requests that are serviced by this same
// endpoint, we don't end up in an infinite recursion
//
if (_isInitializing)
return;
_isInitializing = true;
try
{
//
// load the muse.xml descriptor file
//
Environment env = createEnvironment();
DeploymentDescriptor dd = createDeploymentDescriptor();
Document ddXML = env.getDocument(DescriptorConstants.DESCRIPTOR_FILE_NAME);
dd.load(ddXML, env);
//
// put all custom serializers in the serializer registry
//
Collection serializerDefinitions = dd.getSerializerDefinitions();
Iterator i = serializerDefinitions.iterator();
SerializerRegistry registry = SerializerRegistry.getInstance();
while (i.hasNext())
{
SerializerDefinition next = (SerializerDefinition)i.next();
Serializer ser = next.create();
Class type = ser.getSerializableType();
Class arrayType = ReflectUtils.getArrayClassFromClass(type);
Serializer arraySer = new ArraySerializer(arrayType, ser);
registry.registerSerializer(type, ser);
registry.registerSerializer(arrayType, arraySer);
}
//
// create the router, which will instantiate resources that
// are specified in the deployment descriptor (using the
// /muse/resource-type/@instances-at-startup attribute)
//
RouterDefinition routerDefinition = dd.getRouterDefinition();
_router = routerDefinition.newInstance();
_router.initialize();
_hasBeenInitialized = true;
}
catch (Throwable fault)
{
_hasFailedToInitialize = true;
_causeOfFailure = SoapUtils.convertToFault(fault);
//
// the router didn't finish initializing, so there's probably
// no log to write to. just print to the console
//
fault.printStackTrace();
}
finally
{
_isInitializing = false;
}
}
public boolean hasBeenInitialized()
{
return _hasBeenInitialized;
}
public boolean hasBeenShutdown()
{
return _hasBeenShutdown;
}
public boolean hasFailedToInitialize()
{
return _hasFailedToInitialize;
}
public SoapFault getCauseOfFailure()
{
return _causeOfFailure;
}
public void shutdown()
throws SoapFault
{
_router.shutdown();
_router = null;
_hasBeenShutdown = true;
}
}