/* * Copyright to the original author or authors. * * 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.rioproject.impl.servicebean; import com.sun.jini.reliableLog.LogHandler; import com.sun.jini.reliableLog.ReliableLog; import net.jini.core.discovery.LookupLocator; import net.jini.discovery.DiscoveryGroupManagement; import net.jini.discovery.DiscoveryLocatorManagement; import net.jini.discovery.DiscoveryManagement; import org.rioproject.servicebean.ServiceBeanContext; import org.rioproject.opstring.ServiceBeanConfig; import org.rioproject.opstring.ServiceElement; import org.rioproject.impl.persistence.PersistentStore; import org.rioproject.impl.persistence.SnapshotHandler; import org.rioproject.impl.persistence.StoreException; import org.rioproject.impl.persistence.SubStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; /** * Manages a persistent {@link org.rioproject.servicebean.ServiceBeanContext} * * @author Dennis Reedy */ public class ServiceBeanContextManager { /** * The ServiceBeanContext for the service. This value may be * <code>null</code> */ private ServiceBeanContext context; /** * The LogHandler that will manage the persistent attributes for the * ServiceBeanContext and service attribute list */ private ContextAttributeLogHandler attributeLogHandler = new ContextAttributeLogHandler(); /** the Logger for this component */ private static final Logger logger = LoggerFactory.getLogger("org.rioproject.impl.servicebean"); /** * Create a ServiceBeanContextManager * * @param context ServiceBeanContext */ public ServiceBeanContextManager(ServiceBeanContext context) { this.context = context; } /** * Get the <code>ContextAttributeLogHandler</code> object for this * <code>ServiceBeanContextManager</code> * * @return The ContextAttributeHandler */ public ContextAttributeLogHandler getContextAttributeLogHandler() { return (attributeLogHandler); } /** * Delegates the snapshot to the <code>ContextAttributeLogHandler</code> * * @param dm the DiscoveryManagement for the service * @exception Exception can raise any exception */ public void takeSnapshot(DiscoveryManagement dm) throws Exception { attributeLogHandler.discoMgmt = dm; attributeLogHandler.takeSnapshot(); } /** * Set the <code>PersistentStore</code> to use for persisting the state of * this service. If there is a log directory that already exists at this * location the persisted <code>ServiceBeanContext</code> state will be * retrieved and returned. <br> * * @param store The PersistentStore * * @return ServiceBeanContext the persisted ServiceBeanContext to use for * service initialization. This value will be <code>null</code> if there * is no context found * * @throws StoreException If the context cannot be restored */ public ServiceBeanContext restoreContext(PersistentStore store) throws StoreException { try { store.acquireMutatorLock(); store.addSubStore(attributeLogHandler); } finally { store.releaseMutatorLock(); } ServiceBeanContext ctxt = attributeLogHandler.getRestoredContext(); if(ctxt != null) context = ctxt; return (ctxt); } /** * Class which implements methods needed to meet the LogHandler interface */ public class ContextAttributeLogHandler extends LogHandler implements SubStore, SnapshotHandler { /** Our persistent store */ ReliableLog log; /** The recovered context. May be null */ ServiceBeanContext restoredContext = null; /** The DiscoveryManagement to use */ DiscoveryManagement discoMgmt = null; static final String logDirName = "ContextAttributes"; public ContextAttributeLogHandler() { super(); } void setDiscoveryManagement(DiscoveryManagement discoMgmt) { this.discoMgmt = discoMgmt; } // Inherit JavaDoc from super-type public void setDirectory(File dir) throws IOException { try { log = new ReliableLog(dir.getCanonicalPath(), this); log.recover(); } catch(IOException e) { logger.error("Problem recovering/creating log", e); throw new IOException("ServiceBeanContextManager: log [" + dir.getCanonicalPath() + "] is corrupted:" + e.getLocalizedMessage()); } } // Inherit JavaDoc from super-type public String subDirectory() { return (logDirName); } // Inherit doc comment from super interface public void snapshot(OutputStream out) throws Exception { if(discoMgmt == null) throw new IllegalArgumentException("DiscoveryManagement cannot be null"); ObjectOutputStream oostream = new ObjectOutputStream(out); oostream.writeUTF(logDirName); oostream.writeObject(context); if(discoMgmt instanceof DiscoveryGroupManagement) { DiscoveryGroupManagement dgm = (DiscoveryGroupManagement)discoMgmt; String[] groups = dgm.getGroups(); if(groups == null) groups = new String[]{"all"}; oostream.writeObject(groups); } else { oostream.writeObject(new String[0]); } if(discoMgmt instanceof DiscoveryLocatorManagement) { DiscoveryLocatorManagement dlm = (DiscoveryLocatorManagement)discoMgmt; oostream.writeObject(dlm.getLocators()); } else { oostream.writeObject(new LookupLocator[0]); } oostream.flush(); } // Inherit doc comment from super interface public void recover(InputStream in) throws Exception { ObjectInputStream oistream = new ObjectInputStream(in); if(!logDirName.equals(oistream.readUTF())) throw new IOException("log from wrong implementation"); DefaultServiceBeanContext serviceBeanContext = (DefaultServiceBeanContext)oistream.readObject(); ServiceElement sElem = serviceBeanContext.getServiceElement(); ServiceBeanConfig sAttr = sElem.getServiceBeanConfig(); try { String[] groups = (String[])oistream.readObject(); LookupLocator[] locators = (LookupLocator[])oistream.readObject(); sAttr.setGroups(groups); sAttr.setLocators(locators); } catch(Throwable t) { logger.error("Couldnt get groups or locators", t); } sElem.setServiceBeanConfig(sAttr); serviceBeanContext.setServiceElement(sElem); restoredContext = serviceBeanContext; } /** * @return the ServiceBeanContext that has been restored. If there is no * state to be restored this method will return <code>null</code> */ public ServiceBeanContext getRestoredContext() { return (restoredContext); } /** * This method always throws <code>UnsupportedOperationException</code> * since <code>ContextAttributeLogHandler</code> should never update a * log. */ public void applyUpdate(Object update) throws Exception { throw new UnsupportedOperationException("ContextAttributeLogHandler : "+ "Recovering log update this "+ "should not happen"); } /** * Used by all the methods that change persistent state to commit the * change to disk */ public void takeSnapshot() throws IOException { log.snapshot(); } public void updatePerformed(int updateCount) { } public void prepareDestroy() { try { if(log != null) log.close(); } catch(IOException e) { logger.warn("Problem closing log during destroy, Ignoring and going on", e); } } } }