/*
* 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 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.Serializer;
import org.apache.muse.core.serializer.SerializerRegistry;
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()
{
//
// sanity check - make sure we only initialize once
//
if (hasBeenInitialized())
return;
//
// 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();
registry.registerSerializer(type, ser);
}
//
// 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;
}
}