/*
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr.core;
import org.exoplatform.commons.utils.SecurityHelper;
import org.exoplatform.services.jcr.core.security.JCRRuntimePermissions;
import org.exoplatform.services.jcr.impl.WorkspaceContainer;
import org.exoplatform.services.jcr.impl.WorkspaceResumer;
import org.exoplatform.services.jcr.impl.backup.ResumeException;
import org.exoplatform.services.jcr.impl.backup.SuspendException;
import org.exoplatform.services.jcr.impl.backup.Suspendable;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.jcr.RepositoryException;
/**
* Created by The eXo Platform SAS .<br> An entry point to the implementation, used for extending
* functionality
*
* @author Gennady Azarenkov
* @version $Id:$
*/
public final class WorkspaceContainerFacade
{
private final String workspaceName;
private final WorkspaceContainer container;
private AtomicBoolean workspaceResumerInit = new AtomicBoolean();
private WorkspaceResumer workspaceResumer;
/**
* @param workspaceName
* @param container
*/
public WorkspaceContainerFacade(String workspaceName, WorkspaceContainer container)
{
this.workspaceName = workspaceName;
this.container = container;
}
private WorkspaceResumer getWorkspaceResumer()
{
if (workspaceResumerInit.get())
return workspaceResumer;
// The WorkspaceResumer can be null so to prevent being affected by the auto registration
// we disable it as we know that it is not needed in that case
this.workspaceResumer = container.getComponentInstanceOfType(WorkspaceResumer.class, false);
workspaceResumerInit.set(true);
return workspaceResumer;
}
/**
* @return workspace name
*/
public final String getWorkspaceName()
{
return this.workspaceName;
}
/**
* Returns list of components of specific type.
*
* @param componentType
* component type
* @return List of Object
*/
public <T> List<T> getComponentInstancesOfType(Class<T> componentType)
{
return container.getComponentInstancesOfType(componentType);
}
/**
* @param key
* - an internal key of internal component
* @return the component
*/
public Object getComponent(Object key)
{
if (key instanceof Class)
return container.getComponentInstanceOfType((Class<?>)key);
else
return container.getComponentInstance(key);
}
public void addComponent(Object component)
{
if (component instanceof Class)
container.registerComponentImplementation((Class<?>)component);
else
container.registerComponentInstance(component);
}
public void addComponent(Object key, Object component)
{
container.registerComponentInstance(key, component);
}
/**
* Returns current workspace state.
*/
public int getState()
{
boolean hasSuspendedComponents = false;
boolean hasResumedComponents = false;
List<Suspendable> suspendableComponents = getComponentInstancesOfType(Suspendable.class);
for (Suspendable component : suspendableComponents)
{
if (component.isSuspended())
{
hasSuspendedComponents = true;
}
else
{
hasResumedComponents = true;
}
}
if (hasSuspendedComponents && !hasResumedComponents)
{
return ManageableRepository.SUSPENDED;
}
else if (!hasSuspendedComponents)
{
return ManageableRepository.ONLINE;
}
else
{
return ManageableRepository.UNDEFINED;
}
}
/**
* Set new workspace state.
*
* @param state
* @throws RepositoryException
*/
public void setState(final int state) throws RepositoryException
{
// Need privileges to manage repository.
SecurityManager security = System.getSecurityManager();
if (security != null)
{
security.checkPermission(JCRRuntimePermissions.MANAGE_REPOSITORY_PERMISSION);
}
try
{
SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<Void>()
{
public Void run() throws RepositoryException
{
switch (state)
{
case ManageableRepository.ONLINE :
resume();
break;
case ManageableRepository.OFFLINE :
suspend();
break;
case ManageableRepository.SUSPENDED :
suspend();
break;
default :
return null;
}
return null;
}
});
}
catch (PrivilegedActionException e)
{
Throwable cause = e.getCause();
if (cause instanceof RepositoryException)
{
throw new RepositoryException(cause);
}
else
{
throw new RuntimeException(cause);
}
}
}
/**
* Suspend all components in workspace.
*
* @throws RepositoryException
*/
private void suspend() throws RepositoryException
{
WorkspaceResumer workspaceResumer = getWorkspaceResumer();
if (workspaceResumer != null)
{
workspaceResumer.onSuspend();
}
List<Suspendable> components = getComponentInstancesOfType(Suspendable.class);
Comparator<Suspendable> c = new Comparator<Suspendable>()
{
public int compare(Suspendable s1, Suspendable s2)
{
return s2.getPriority() - s1.getPriority();
};
};
Collections.sort(components, c);
for (Suspendable component : components)
{
try
{
if (!component.isSuspended())
{
component.suspend();
}
}
catch (SuspendException e)
{
throw new RepositoryException("Can't suspend component", e);
}
}
}
/**
* Set all components online.
*
* @throws RepositoryException
*/
private void resume() throws RepositoryException
{
WorkspaceResumer workspaceResumer = getWorkspaceResumer();
if (workspaceResumer != null)
{
workspaceResumer.onResume();
}
// components should be resumed in reverse order
List<Suspendable> components = getComponentInstancesOfType(Suspendable.class);
Comparator<Suspendable> c = new Comparator<Suspendable>()
{
public int compare(Suspendable s1, Suspendable s2)
{
return s1.getPriority() - s2.getPriority();
};
};
Collections.sort(components, c);
for (Suspendable component : components)
{
try
{
if (component.isSuspended())
{
component.resume();
}
}
catch (ResumeException e)
{
throw new RepositoryException("Can't set component online", e);
}
}
}
}