/*
* $Id: IWSlideSessionBean.java,v 1.40 2009/04/07 12:15:58 laddi Exp $
* Created on 23.10.2004
*
* Copyright (C) 2004 Idega Software hf. All Rights Reserved.
*
* This software is the proprietary information of Idega hf.
* Use is subject to license terms.
*/
package com.idega.slide.business;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.rmi.RemoteException;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpSessionBindingEvent;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpURL;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.SlideToken;
import org.apache.slide.security.Security;
import org.apache.slide.structure.ActionNode;
import org.apache.slide.structure.LinkNode;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.webdav.lib.Privilege;
import org.apache.webdav.lib.WebdavFile;
import org.apache.webdav.lib.WebdavResource;
import org.apache.webdav.lib.util.WebdavStatus;
import com.idega.business.IBOLookupException;
import com.idega.business.IBOSessionBean;
import com.idega.core.accesscontrol.business.LoggedOnInfo;
import com.idega.core.accesscontrol.business.LoginBusinessBean;
import com.idega.core.accesscontrol.business.NotLoggedOnException;
import com.idega.slide.util.AccessControlList;
import com.idega.slide.util.IWSlideConstants;
import com.idega.slide.util.WebdavExtendedResource;
import com.idega.slide.util.WebdavOutputStream;
import com.idega.slide.util.WebdavRootResource;
import com.idega.util.CoreConstants;
import com.idega.util.StringHandler;
import com.idega.util.StringUtil;
/**
*
* Last modified: $Date: 2009/04/07 12:15:58 $ by $Author: laddi $
*
* @author <a href="mailto:gummi@idega.com">Gudmundur Agust Saemundsson</a>
* @version $Revision: 1.40 $
*/
public class IWSlideSessionBean extends IBOSessionBean implements IWSlideSession { //, HttpSessionBindingListener {
// public static final String PATH_DEFAULT_SCOPE_ROOT = "/files";
// public static final String PATH_ROOT = "/";
// public static final String PATH_CURRENT = null;
private WebdavRootResource webdavRootResource = null;
private boolean isLoggedOn = false;
private UsernamePasswordCredentials usersCredentials = null;
private IWSlideService service = null;
private String servletPath = null;
private static final String SLIDE_PASSWORD_ATTRIBUTE_NAME = "iw_slide_password";
private SlideToken _slideToken = null;
// /** The WebDAV resource. */
// private WebdavResource webdavResource = null;
// private HttpURL rootURL = null;
// private WebdavFile homedir = null;
// private String username = null;
// private String password = null;
// private String uri = null;
// private String rootPath = null;
/**
*
*/
public IWSlideSessionBean() {
super();
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpSessionBindingListener#valueBound(javax.servlet.http.HttpSessionBindingEvent)
*/
public void valueBound(HttpSessionBindingEvent arg0) {}
/* (non-Javadoc)
* @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(javax.servlet.http.HttpSessionBindingEvent)
*/
public void valueUnbound(HttpSessionBindingEvent arg0) {
close();
}
public IWSlideService getIWSlideService(){
if(this.service == null){
try {
this.service = (IWSlideService)this.getServiceInstance(IWSlideService.class);
}
catch (IBOLookupException e) {
e.printStackTrace();
}
}
return this.service;
}
/**
* @return returns full name of the current user. Returns <code>null</code> if user is not logged on.
*/
public String getUserFullName() {
try {
if (getCurrentUser() != null) {
return getCurrentUser().getName();
}
} catch (NotLoggedOnException e) {
return null;
}
return null;
}
public String getWebdavServerURI(){
if(this.servletPath == null){
try {
this.servletPath = getIWSlideService().getWebdavServerURI();
}
catch (RemoteException e) {
e.printStackTrace();
}
}
return this.servletPath;
}
public UsernamePasswordCredentials getUserCredentials() throws RemoteException{
LoggedOnInfo lInfo = LoginBusinessBean.getLoggedOnInfo(getUserContext());
if(lInfo!=null){
String password = (String)lInfo.getAttribute(SLIDE_PASSWORD_ATTRIBUTE_NAME);
if(password == null){
password = StringHandler.getRandomString(10);
lInfo.setAttribute(SLIDE_PASSWORD_ATTRIBUTE_NAME,password);
}
if(getUserContext().isSuperAdmin()){
return getIWSlideService().getRootUserCredentials();
} else {
return new UsernamePasswordCredentials(lInfo.getLogin(),password);
}
}
return null;
}
/**
* This returns a wrapper for the root webdavresoure. Only one instance of this object is created for each session.
*/
public WebdavRootResource getWebdavRootResource() throws HttpException, IOException{
boolean tmpIsLoggedOn = getUserContext().isLoggedOn();
//if("resource is null" && ("has logged on/off" || ("is logged on" && "has some usersCredentials" && "the credential does not match his current login, that is he has logged in as some other user")))
if(this.webdavRootResource != null && (this.isLoggedOn != tmpIsLoggedOn || (tmpIsLoggedOn && this.usersCredentials != null && !(this.usersCredentials).getUserName().equals(getUserContext().getRemoteUser())))){
String userName = (this.usersCredentials).getUserName();
//extra check because "Administrator" is "root"
if(!(userName.equals("root") && getUserContext().isSuperAdmin())){
this.webdavRootResource.close();
this.webdavRootResource = null;
this.usersCredentials = null;
this.isLoggedOn = !this.isLoggedOn;
}
}
if(this.webdavRootResource == null || this.webdavRootResource.isClosed()){
this.webdavRootResource=null;
if(this.usersCredentials == null){
if(tmpIsLoggedOn){
this.usersCredentials = getUserCredentials();
this.isLoggedOn=true;
}
}
WebdavResource resource;
if(this.usersCredentials!=null){
resource = new WebdavResource(getIWSlideService().getWebdavServerURL(this.usersCredentials));
} else {
resource = new WebdavResource(getIWSlideService().getWebdavServerURL());
}
resource.setFollowRedirects(true);
this.webdavRootResource = new WebdavRootResource(resource);
}
return this.webdavRootResource;
}
public WebdavExtendedResource getWebdavResource(String path) throws HttpException, IOException, RemoteException {
return getWebdavResource(path, Boolean.FALSE);
}
public WebdavExtendedResource getResource(String path, boolean localResource) throws HttpException, IOException, RemoteException, RemoteException {
return getWebdavResource(path, Boolean.FALSE, localResource);
}
public WebdavExtendedResource getWebdavResource(String path, boolean useRootCredentials) throws HttpException, IOException, RemoteException {
return getWebdavResource(path, useRootCredentials, Boolean.TRUE);
}
private WebdavExtendedResource getWebdavResource(String path, boolean useRootCredentials, boolean localResource) throws HttpException, IOException,
RemoteException {
IWSlideService service = getIWSlideService();
return service.getWebdavExtendedResource(path, useRootCredentials ? service.getRootUserCredentials() : getUserCredentials(), localResource);
}
/**
* <p>
* Gets an URL to the WebdavServer with set credentials
* </p>
* @param path
* @return
*/
public HttpURL getURL(String path){
IWSlideService service = getIWSlideService();
try {
return service.getWebdavServerURL(getUserCredentials(), path);
}
catch (RemoteException e) {
throw new RuntimeException(e);
}
}
/**
* Gets a file representation for the given path
*/
public File getFile(String path)throws URIException{
WebdavFile file = null;
file = new WebdavFile(getURL(path));
return file;
}
/**
* Gets an inputstream for reading the file on the given path
* @throws IOException
* @throws
*/
public InputStream getInputStream(String path)throws IOException{
WebdavResource resource = getWebdavResource(path);
return resource.getMethodData();
}
public InputStream getInputStream(String path, boolean useRootCredentials) throws IOException{
WebdavResource resource = getWebdavResource(path, useRootCredentials);
return resource.getMethodData();
}
public OutputStream getOutputStream(File file)throws IOException{
return getOutputStream(file.getAbsolutePath());
}
/**
* Gets an outputstream for writing to the file on the given path
* @throws IOException
* @throws
*/
public OutputStream getOutputStream(String path)throws IOException{
WebdavResource resource = getWebdavResource(path);
return new WebdavOutputStream(resource);
}
public String getURI(String path) throws RemoteException{
return getIWSlideService().getURI(path);
}
public String getPath(String uri) throws RemoteException{
String uriPrefix = getWebdavServerURI();
return StringUtil.isEmpty(uri) ? null : ((uri.startsWith(uriPrefix))?uri.substring(uriPrefix.length()):uri);
}
/**
* Differs from the method in the service bean a little. The service bean uses the root credentials but this uses the current users credentials.
*/
public boolean getExistence(String path) throws HttpException, IOException{
if(path==null){
return false;
}
try {
String pathToCheck = ((path.startsWith(getWebdavServerURI()))?path:getURI(path));
Enumeration prop = getWebdavRootResource().propfindMethod(pathToCheck, WebdavResource.DISPLAYNAME);
return !(prop == null || !prop.hasMoreElements());
}
catch (HttpException e) {
if(e.getReasonCode()==WebdavStatus.SC_NOT_FOUND){
return false;
} else {
throw e;
}
}
// return getWebdavRootResource().headMethod(((path.startsWith(getWebdavServerURI()))?path:getURI(path)));
}
public void close(){
if(this.webdavRootResource != null){
try {
this.webdavRootResource.close();
this.webdavRootResource = null;
}
catch (IOException e) {
e.printStackTrace();
}
}
}
public AccessControlList getAccessControlList(String path) throws HttpException, IOException{
WebdavRootResource rResource = getWebdavRootResource();
return getIWSlideService().getAccessControlList(path, rResource);
}
public boolean storeAccessControlList(AccessControlList acl) throws HttpException, IOException{
WebdavRootResource rResource = getWebdavRootResource();
return getIWSlideService().storeAccessControlList(acl, rResource);
}
public String getUserHomeFolder() throws RemoteException {
String loginName = getUserContext().getRemoteUser();
if (loginName != null) {
return getIWSlideService().getUserHomeFolderPath(loginName);
}
return null;
}
/**
* Returns a SlideToken using the authentication information of the IW login system
*
* @return a new SlideToken instance
**/
private SlideToken getSlideToken() {
if(this._slideToken == null){
throw new RuntimeException("["+this.getClass().getName()+"]: Requesting SlideToken but token has not been set. Check if IWSlideAuthenticator filter is mapped right (/*) in web.xml");
// // This code is borrowed from org.apache.slide.webdav.util.WebdavUtils#getSlideToken(HttpServletRequest)
// // and altered since we just have session and not requst object.
//
// CredentialsToken credentialsToken;
// Principal principal = getUserContext().getUserPrincipal();
//
// // store the current principal in the session, to get around a bug in
// // IE 5 where the authentication info is not submitted by IE when
// // doing a HEAD request.
// if (principal == null) {
// credentialsToken = new CredentialsToken("");
// } else {
// // because the principal is not guaranteed to be serializable
// // and could thus create problems in a distributed deployment
// // we store the principal name instead of the principal itself
//// session.setAttribute(CREDENTIALS_ATTRIBUTE, principal.getName());
// credentialsToken = new CredentialsToken(principal);
// }
//
// SlideToken token = new SlideTokenImpl(credentialsToken);
// token.setEnforceLockTokens(true);
//
// // store session attributes in token parameters to pass them through
// // to the stores
// for(Enumeration e = getUserContext().getSeAttributeNames(); e.hasMoreElements();) {
// String name = (String)e.nextElement();
// token.addParameter(name, getUserContext().getSessionAttribute(name));
// }
// return _slideToken;
}
return this._slideToken;
}
/* (non-Javadoc)
* @see com.idega.slide.business.IWSlideSession#setSlideToken(org.apache.slide.common.SlideToken)
*/
public void setSlideToken(Object slideToken) {
setSlideToken((SlideToken)slideToken);
}
/* (non-Javadoc)
* @see com.idega.slide.business.IWSlideSession#setSlideToken(org.apache.slide.common.SlideToken)
*/
private void setSlideToken(SlideToken slideToken) {
this._slideToken = slideToken;
}
private Security getSecurity() throws RemoteException{
return getIWSlideService().getSecurityHelper();
}
public boolean hasPermission(String resourcePath, Privilege privilege) throws RemoteException {
return hasPermission(resourcePath, privilege, false);
}
private boolean hasPermission(String resourcePath, Privilege privilege, boolean decoded) throws RemoteException {
if (StringUtil.isEmpty(resourcePath) || privilege == null) {
Logger.getLogger(getClass().getName()).warning("Either resource path is not defined ('" + resourcePath + "') or the privilege is not defined: " + privilege);
return false;
}
try {
return getSecurity().hasPermission(getSlideToken(), getObjectNode(resourcePath), getActionNode(privilege));
} catch (ObjectNotFoundException e) {
if (decoded) {
e.printStackTrace();
} else {
try {
return hasPermission(URLDecoder.decode(resourcePath, CoreConstants.ENCODING_UTF8), privilege, true);
} catch (UnsupportedEncodingException uee) {
uee.printStackTrace();
return false;
}
}
} catch (ServiceAccessException e) {
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Error resolving permission for resource '" + resourcePath + "', privilege: " + privilege, e);
} catch (Exception e) {
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Error resolving permission for resource '" + resourcePath + "', privilege: " + privilege, e);
}
return false;
}
/**
* @param resourcePath
* @return
*/
private LinkNode getObjectNode(String resourcePath) throws RemoteException {
return new LinkNode(getPath(resourcePath));
}
/**
* @param action
* @return
*/
private ActionNode getActionNode(Privilege privilege) {
String path = IWSlideConstants.PATH_ACTIONS.concat(CoreConstants.SLASH).concat(privilege.getName());
return ActionNode.getActionNode(path);
}
/**
* Creates all the folders in path
* @param path Path with all the folders to create.
* Should hold all the folders after Server URI (Typically /cms/content/)
* @throws HttpException
* @throws RemoteException
* @throws IOException
* @return true if it needed to create the folders
*/
public boolean createAllFoldersInPath(String path) throws HttpException, RemoteException, IOException {
IWSlideService slideService = getIWSlideService();
return slideService.createAllFoldersInPath(path,getUserCredentials());
}
/**
*
* @param folderURI the path to the folder
* @return true if the path refers to a folder, checks as the current user, false if he doesn't have the priviledges to the folder
*/
public boolean isFolder(String folderURI) {
WebdavResource resource;
try {
resource = getWebdavResource(folderURI);
return resource.isCollection();
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}