Java tutorial
/* * $Header: /var/chroot/cvs/cvs/factsheetDesigner/extern/jakarta-slide-server-src-2.1-iPlus Edit/src/stores/org/apache/slide/store/mem/AbstractTransientStore.java,v 1.2 2006-01-22 22:49:06 peter-cvs Exp $ * $Revision: 1.2 $ * $Date: 2006-01-22 22:49:06 $ * * ==================================================================== * * Copyright 1999-2002 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.slide.store.mem; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import org.apache.commons.transaction.memory.ConflictException; import org.apache.commons.transaction.memory.TransactionalMapWrapper; import org.apache.commons.transaction.memory.jca.MapXAResource; import org.apache.commons.transaction.util.LoggerFacade; import org.apache.slide.common.AbstractServiceBase; import org.apache.slide.common.NamespaceAccessToken; import org.apache.slide.common.ServiceAccessException; import org.apache.slide.common.ServiceConnectionFailedException; import org.apache.slide.common.ServiceDisconnectionFailedException; import org.apache.slide.common.ServiceInitializationFailedException; import org.apache.slide.common.ServiceParameterErrorException; import org.apache.slide.common.ServiceParameterMissingException; import org.apache.slide.common.ServiceResetFailedException; import org.apache.slide.util.logger.Logger; import org.apache.slide.util.logger.TxLogger; /** * Base class for the stores that what to store its data transient in a * map. * * <p>Implementations access the backing map only via {@link #put(Object, Object)}, * {@link #get(Object)} and {@link #remove(Object)}. * * <p>The backed map can be any class that is derived from * {@link org.apache.commons.transaction.memory.TransactionalMapWrapper}. * * <p>The class may be configured in the <code>domain.xml</code> using the * parameter <code>map-classname</code>. * Default is {@link org.apache.commons.transaction.memory.OptimisticMapWrapper}. * * */ public abstract class AbstractTransientStore extends AbstractServiceBase { static final String MAP_IMPL_PARAMETER = "map-classname"; static final String MAP_IMPL_PARAMETER_DEFAULT = "org.apache.commons.transaction.memory.OptimisticMapWrapper"; private Map parameters = null; private boolean isConnected = false; /** * The map containing the stored content. */ private TransactionalMapWrapper store = null; /** * The XAResource to delegate all XA requests. */ private MapXAResource xaResource = null; // ----------------------------------------------------- XAResource Mathods public void start(Xid xid, int flags) throws XAException { debug("start {0} {1}", xid, Integer.toString(flags)); this.xaResource.start(xid, flags); } public void commit(Xid xid, boolean onePhase) throws XAException { debug("commit {0} {1}", xid, onePhase ? "true" : "false"); try { this.xaResource.commit(xid, onePhase); } catch (ConflictException e) { this.xaResource.rollback(xid); // TODO it would be great if we could throw something // that would (on the webdav layer) leads to a 409 Conflict // instead of 500 Internal Server Error throw new XAException(XAException.XA_RBOTHER); // ?? } } public int prepare(Xid xid) throws XAException { debug("prepare {0}", xid); return this.xaResource.prepare(xid); } public void end(Xid xid, int flags) throws XAException { debug("end {0} {1}", xid, Integer.toString(flags)); this.xaResource.end(xid, flags); } public void rollback(Xid xid) throws XAException { debug("rollback {0}", xid); this.xaResource.rollback(xid); } public Xid[] recover(int flag) throws XAException { debug("recover {0}", Integer.toString(flag)); return this.xaResource.recover(flag); } public void forget(Xid xid) throws XAException { debug("forget {0}", xid); this.xaResource.forget(xid); } public int getTransactionTimeout() throws XAException { return this.xaResource.getTransactionTimeout(); } public boolean setTransactionTimeout(int seconds) throws XAException { return this.xaResource.setTransactionTimeout(seconds); } public boolean isSameRM(XAResource xares) throws XAException { return this == xares; } // ------------------------------------- Store accessors for implementations protected void put(Object key, Object value) { this.store.put(key, value); } protected Object get(Object key) { return this.store.get(key); } protected Object remove(Object key) { return this.store.remove(key); } // ------------------------------------------------ ContextTuple InnerClass public void setParameters(Hashtable parameters) throws ServiceParameterErrorException, ServiceParameterMissingException { this.parameters = new HashMap(parameters); } protected String getParameter(String name) { if (this.parameters != null) { return (String) this.parameters.get(name); } else { throw new IllegalStateException("Parameter not yet set!"); } } public void initialize(NamespaceAccessToken token) throws ServiceInitializationFailedException { super.initialize(token); TxLogger txLogger = new TxLogger(getLogger(), LogChannel()); String param = (String) this.parameters.get(MAP_IMPL_PARAMETER); if (param == null) { param = MAP_IMPL_PARAMETER_DEFAULT; } try { info("Initializing {0} using {1}.", getClass().getName(), param); Map toBeWrapped = new HashMap(); Class mapClass = Class.forName(param); try { Class[] ctorFormalArgs = { Map.class, LoggerFacade.class }; Constructor ctor = mapClass.getConstructor(ctorFormalArgs); Object[] ctorArgs = { toBeWrapped, txLogger }; this.store = (TransactionalMapWrapper) ctor.newInstance(ctorArgs); } catch (NoSuchMethodException e) { // try next try { Class[] ctorFormalArgs = { Map.class }; Constructor ctor = mapClass.getConstructor(ctorFormalArgs); Object[] ctorArgs = { toBeWrapped }; this.store = (TransactionalMapWrapper) ctor.newInstance(ctorArgs); } catch (NoSuchMethodException ee) { error("Initialization error: ", ee); throw new ServiceInitializationFailedException(this, ee); } } } catch (ClassNotFoundException e) { error("Initialization error: ", e); throw new ServiceInitializationFailedException(this, e); } catch (InstantiationException e) { error("Initialization error: ", e); throw new ServiceInitializationFailedException(this, e); } catch (IllegalAccessException e) { error("Initialization error: ", e); throw new ServiceInitializationFailedException(this, e); } catch (InvocationTargetException e) { error("Initialization error: ", e); throw new ServiceInitializationFailedException(this, e); } catch (ClassCastException e) { error("Initialization error: ", e); throw new ServiceInitializationFailedException(this, "class in parameter '" + MAP_IMPL_PARAMETER + "' must " + "be derived from TransactionalMapWrapper"); } this.xaResource = new MapXAResource(this.store); // FIXME can't set logging because methods are not public, and // ctor doesn't take a loggerFacade } public void connect() throws ServiceConnectionFailedException { this.isConnected = true; } public void disconnect() throws ServiceDisconnectionFailedException { this.isConnected = false; } public void reset() throws ServiceResetFailedException { } public boolean isConnected() throws ServiceAccessException { return this.isConnected; } // ------------------------------------------------------------------- protected String LogChannel() { return LOG_CHANNEL; } protected void debug(String msg, Object o) { if (this.getLogger().isEnabled(Logger.DEBUG)) { Object[] args = { o }; this.getLogger().log(MessageFormat.format(msg, args), LogChannel(), Logger.DEBUG); } } protected void debug(String msg, Object o1, Object o2) { if (this.getLogger().isEnabled(Logger.DEBUG)) { Object[] args = { o1, o2 }; this.getLogger().log(MessageFormat.format(msg, args), LogChannel(), Logger.DEBUG); } } private void info(String msg, Object o1, Object o2) { if (this.getLogger().isEnabled(Logger.INFO)) { Object[] args = { o1, o2 }; this.getLogger().log(MessageFormat.format(msg, args), LogChannel(), Logger.INFO); } } private void error(String msg, Throwable t) { if (this.getLogger().isEnabled(Logger.INFO)) { this.getLogger().log(msg, t, LogChannel(), Logger.INFO); } } /** * Empty enumeration. */ protected static Enumeration EMPTY_ENUM = new Enumeration() { public boolean hasMoreElements() { return false; } public Object nextElement() { throw new NoSuchElementException(); } }; /** * Enumeration wrapper for an Iterator. */ protected static class IteratorEnum implements Enumeration { private Iterator iterator; public IteratorEnum(Iterator iterator) { this.iterator = iterator; } public boolean hasMoreElements() { return this.iterator.hasNext(); } public Object nextElement() { return this.iterator.next(); } } }