/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH (http://www.alkacon.com)
*
* This library 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 library 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.
*
* For further information about Alkacon Software GmbH, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.gwt.client;
import org.opencms.db.CmsResourceState;
import org.opencms.gwt.client.rpc.CmsRpcAction;
import org.opencms.gwt.client.rpc.CmsRpcPrefetcher;
import org.opencms.gwt.client.ui.CmsNotification;
import org.opencms.gwt.shared.CmsCoreData;
import org.opencms.gwt.shared.CmsLockInfo;
import org.opencms.gwt.shared.rpc.I_CmsCoreService;
import org.opencms.gwt.shared.rpc.I_CmsCoreServiceAsync;
import org.opencms.gwt.shared.rpc.I_CmsVfsService;
import org.opencms.gwt.shared.rpc.I_CmsVfsServiceAsync;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
/**
* Client side core data provider.<p>
*
* @since 8.0.0
*
* @see org.opencms.gwt.CmsGwtActionElement
*/
public final class CmsCoreProvider extends CmsCoreData {
/** Path to system folder. */
public static final String VFS_PATH_SYSTEM = "/system/";
/** Internal instance. */
private static CmsCoreProvider INSTANCE;
/** The core service instance. */
private static I_CmsCoreServiceAsync SERVICE;
/** The vfs-service instance. */
private static I_CmsVfsServiceAsync VFS_SERVICE;
/** The client time when the data is loaded. */
private long m_clientTime;
/** Flag which indicates whether we are in Internet Explorer 7. */
private boolean m_isIe7;
/**
* Prevent instantiation.<p>
*/
protected CmsCoreProvider() {
super((CmsCoreData)CmsRpcPrefetcher.getSerializedObject(getService(), DICT_NAME));
m_clientTime = System.currentTimeMillis();
I_CmsUserAgentInfo userAgentInfo = GWT.create(I_CmsUserAgentInfo.class);
m_isIe7 = userAgentInfo.isIE7();
}
/**
* Returns the client message instance.<p>
*
* @return the client message instance
*/
public static CmsCoreProvider get() {
if (INSTANCE == null) {
INSTANCE = new CmsCoreProvider();
}
return INSTANCE;
}
/**
* Returns the core service instance.<p>
*
* @return the core service instance
*/
public static I_CmsCoreServiceAsync getService() {
if (SERVICE == null) {
SERVICE = GWT.create(I_CmsCoreService.class);
String serviceUrl = CmsCoreProvider.get().link("org.opencms.gwt.CmsCoreService.gwt");
((ServiceDefTarget)SERVICE).setServiceEntryPoint(serviceUrl);
}
return SERVICE;
}
/**
* Returns the vfs service instance.<p>
*
* @return the vfs service instance
*/
public static I_CmsVfsServiceAsync getVfsService() {
if (VFS_SERVICE == null) {
VFS_SERVICE = GWT.create(I_CmsVfsService.class);
String serviceUrl = CmsCoreProvider.get().link("org.opencms.gwt.CmsVfsService.gwt");
((ServiceDefTarget)VFS_SERVICE).setServiceEntryPoint(serviceUrl);
}
return VFS_SERVICE;
}
/**
* Adds the current site root of this context to the given resource name.<p>
*
* @param sitePath the resource name
*
* @return the translated resource name including site root
*
* @see #removeSiteRoot(String)
*/
public String addSiteRoot(String sitePath) {
if (sitePath == null) {
return null;
}
String siteRoot = getAdjustedSiteRoot(getSiteRoot(), sitePath);
StringBuffer result = new StringBuffer(128);
result.append(siteRoot);
if (((siteRoot.length() == 0) || (siteRoot.charAt(siteRoot.length() - 1) != '/'))
&& ((sitePath.length() == 0) || (sitePath.charAt(0) != '/'))) {
// add slash between site root and resource if required
result.append('/');
}
result.append(sitePath);
return result.toString();
}
/**
* Creates a new CmsUUID.<p>
*
* @param callback the callback to execute
*/
public void createUUID(final AsyncCallback<CmsUUID> callback) {
// do not stop/start since we do not want to give any feedback to the user
CmsRpcAction<CmsUUID> action = new CmsRpcAction<CmsUUID>() {
/**
* @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
*/
@Override
public void execute() {
getService().createUUID(this);
}
/**
* @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
*/
@Override
protected void onResponse(CmsUUID result) {
callback.onSuccess(result);
}
};
action.execute();
}
/**
* Returns the adjusted site root for a resource using the provided site root as a base.<p>
*
* Usually, this would be the site root for the current site.
* However, if a resource from the <code>/system/</code> folder is requested,
* this will be the empty String.<p>
*
* @param siteRoot the site root of the current site
* @param resourcename the resource name to get the adjusted site root for
*
* @return the adjusted site root for the resource
*/
public String getAdjustedSiteRoot(String siteRoot, String resourcename) {
if (resourcename.startsWith(VFS_PATH_SYSTEM)) {
return "";
} else {
return siteRoot;
}
}
/**
* Returns the approximate time on the server.<p>
*
* @return the approximate server time
*/
public long getEstimatedServerTime() {
return m_clientTime + (System.currentTimeMillis() - m_clientTime);
}
/**
* Fetches the state of a resource from the server.<p>
*
* @param structureId the structure id of the resource
* @param callback the callback which should receive the result
*/
public void getResourceState(final CmsUUID structureId, final AsyncCallback<CmsResourceState> callback) {
CmsRpcAction<CmsResourceState> action = new CmsRpcAction<CmsResourceState>() {
/**
* @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
*/
@Override
public void execute() {
start(0, false);
getService().getResourceState(structureId, this);
}
/**
* @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
*/
@Override
protected void onResponse(CmsResourceState result) {
stop(false);
callback.onSuccess(result);
}
};
action.execute();
}
/**
* Returns if the current user agent is IE7.<p>
*
* @return <code>true</code> if the current user agent is IE7
*/
public boolean isIe7() {
return m_isIe7;
}
/**
* Returns an absolute link given a site path.<p>
*
* @param sitePath the site path
*
* @return the absolute link
*/
public String link(String sitePath) {
return CmsStringUtil.joinPaths(getVfsPrefix(), sitePath);
}
/**
* Locks the given resource with a temporary lock, synchronously.<p>
*
* @param structureId the resource structure id
*
* @return <code>true</code> if succeeded, if not a a warning is already shown to the user
*/
public boolean lock(final CmsUUID structureId) {
CmsRpcAction<String> lockAction = new CmsRpcAction<String>() {
/**
* @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
*/
@Override
public void execute() {
setLoadingMessage(Messages.get().key(Messages.GUI_LOCKING_0));
start(200, false);
getService().lockTemp(structureId, this);
}
/**
* @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
*/
@Override
public void onResponse(String result) {
stop(false);
if (result == null) {
// ok
return;
}
// unable to lock
final String text = Messages.get().key(Messages.GUI_LOCK_NOTIFICATION_2, structureId, result);
CmsNotification.get().sendDeferred(CmsNotification.Type.WARNING, text);
}
};
return lockAction.executeSync() == null;
}
/**
* Locks the given resource with a temporary lock, synchronously and additionally checking that
* the given resource has not been modified after the given timestamp.<p>
*
* @param structureId the resource structure id
* @param modification the timestamp to check
*
* @return <code>null</code> if successful, else an error message
*/
public CmsLockInfo lockTempAndCheckModification(final CmsUUID structureId, final long modification) {
// lock the sitemap
CmsRpcAction<CmsLockInfo> lockAction = new CmsRpcAction<CmsLockInfo>() {
/**
* @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
*/
@Override
public void execute() {
setLoadingMessage(Messages.get().key(Messages.GUI_LOCKING_0));
start(200, false);
getService().lockTempAndCheckModification(structureId, modification, this);
}
/**
* @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
*/
@Override
public void onResponse(CmsLockInfo result) {
stop(false);
}
};
return lockAction.executeSync();
}
/**
* Removes the current site root prefix from the given root path,
* that is adjusts the resource name for the current site root.<p>
*
* If the resource name does not start with the current site root,
* it is left untouched.<p>
*
* @param rootPath the resource name
*
* @return the resource name adjusted for the current site root
*
* @see #addSiteRoot(String)
*/
public String removeSiteRoot(String rootPath) {
String siteRoot = getAdjustedSiteRoot(getSiteRoot(), rootPath);
if ((siteRoot == getSiteRoot())
&& rootPath.startsWith(siteRoot)
&& ((rootPath.length() == siteRoot.length()) || (rootPath.charAt(siteRoot.length()) == '/'))) {
rootPath = rootPath.substring(siteRoot.length());
}
return rootPath;
}
/**
* Returns the absolute link to the given root path.<p>
*
* @param rootPath the root path
*
* @return the absolute link
*/
public String substituteLinkForRootPath(final String rootPath) {
CmsRpcAction<String> action = new CmsRpcAction<String>() {
@Override
public void execute() {
getVfsService().substituteLinkForRootPath(getSiteRoot(), rootPath, this);
}
@Override
protected void onResponse(String result) {
// nothing to do here
}
};
return action.executeSync();
}
/**
* Unlocks the current resource.<p>
*
* @return <code>true</code> if succeeded
*
* @see #unlock(CmsUUID)
*/
public boolean unlock() {
return unlock(getStructureId());
}
/**
* Unlocks the given resource, synchronously.<p>
*
* @param structureId the resource structure id
*
* @return <code>true</code> if succeeded, if not a a warning is already shown to the user
*/
public boolean unlock(final CmsUUID structureId) {
// lock the sitemap
CmsRpcAction<String> unlockAction = new CmsRpcAction<String>() {
/**
* @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
*/
@Override
public void execute() {
setLoadingMessage(Messages.get().key(Messages.GUI_UNLOCKING_0));
start(200, false);
getService().unlock(structureId, this);
}
/**
* @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
*/
@Override
public void onResponse(String result) {
stop(false);
if (result == null) {
// ok
return;
}
// unable to lock
String text = Messages.get().key(Messages.GUI_UNLOCK_NOTIFICATION_2, structureId.toString(), result);
CmsNotification.get().send(CmsNotification.Type.WARNING, text);
}
};
return unlockAction.executeSync() == null;
}
}