<classpathentry kind="lib" path="lib/gwtquery-1.0.0-20110116.074055-7.jar"/>
<classpathentry kind="lib" path="dependencies/selenium-server-standalone-2.0b1.jar"/>
<classpathentry kind="lib" path="dependencies/gwt-incubator-20101117-r1766.jar"/>
+ <classpathentry kind="lib" path="lib/milton/aopalliance-1.0.jar"/>
+ <classpathentry kind="lib" path="lib/milton/commons-beanutils-1.8.2.jar"/>
+ <classpathentry kind="lib" path="lib/milton/commons-codec-1.4.jar"/>
+ <classpathentry kind="lib" path="lib/milton/commons-collections-3.2.jar"/>
+ <classpathentry kind="lib" path="lib/milton/commons-fileupload-1.2.1.jar"/>
+ <classpathentry kind="lib" path="lib/milton/commons-io-1.1.jar"/>
+ <classpathentry kind="lib" path="lib/milton/commons-lang-2.4.jar"/>
+ <classpathentry kind="lib" path="lib/milton/commons-logging-1.1.1.jar"/>
+ <classpathentry kind="lib" path="lib/milton/ezmorph-1.0.6.jar"/>
+ <classpathentry kind="lib" path="lib/milton/ftplet-api-1.0.1.jar"/>
+ <classpathentry kind="lib" path="lib/milton/ftpserver-core-1.0.1.jar"/>
+ <classpathentry kind="lib" path="lib/milton/jcl-over-slf4j-1.5.2.jar"/>
+ <classpathentry kind="lib" path="lib/milton/jdom-1.1.jar"/>
+ <classpathentry kind="lib" path="lib/milton/json-lib-2.2.3.jar"/>
+ <classpathentry kind="lib" path="lib/milton/log4j-1.2.14.jar"/>
+ <classpathentry kind="lib" path="lib/milton/milton-api-1.5.7-SNAPSHOT.jar"/>
+ <classpathentry kind="lib" path="lib/milton/milton-console-1.5.7-SNAPSHOT.jar"/>
+ <classpathentry kind="lib" path="lib/milton/milton-filesystem-1.5.7-SNAPSHOT.jar"/>
+ <classpathentry kind="lib" path="lib/milton/milton-ftp-1.5.7-SNAPSHOT.jar"/>
+ <classpathentry kind="lib" path="lib/milton/milton-servlet-1.5.7-SNAPSHOT.jar"/>
+ <classpathentry kind="lib" path="lib/milton/mime-util-2.1.3.jar"/>
+ <classpathentry kind="lib" path="lib/milton/mina-core-2.0.0-M4.jar"/>
+ <classpathentry kind="lib" path="lib/milton/slf4j-api-1.5.8.jar"/>
+ <classpathentry kind="lib" path="lib/milton/slf4j-log4j12-1.5.2.jar"/>
+ <classpathentry kind="lib" path="lib/milton/spring-2.5.6.jar"/>
+ <classpathentry kind="lib" path="lib/milton/spring-beans-2.5.6.jar"/>
+ <classpathentry kind="lib" path="lib/milton/spring-context-2.5.6.jar"/>
+ <classpathentry kind="lib" path="lib/milton/spring-context-support-2.5.6.jar"/>
+ <classpathentry kind="lib" path="lib/milton/spring-core-2.5.6.jar"/>
+ <classpathentry kind="lib" path="lib/milton/spring-web-2.5.6.jar"/>
+ <classpathentry kind="lib" path="lib/milton/spring-webmvc-2.5.6.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<pathelement location="${solr.lib}/lucene-core-2.9.3.jar"/>
<pathelement location="${solr.lib}/lucene-analyzers-2.9.3.jar"/>
<pathelement location="${deps.dir}/${selenium-server.filename}"/>
+ <fileset dir="${lib.dir}/milton">
+ <include name="**/*.jar" />
+ </fileset>
</path>
<target name="check-jboss">
<zipfileset dir="${build.dir}" prefix="WEB-INF/lib">
<include name="webdav.jar" />
</zipfileset>
+ <zipfileset dir="${lib.dir}/milton" prefix="WEB-INF/lib">
+ <include name="**/*.jar" />
+ </zipfileset>
</jar>
</target>
--- /dev/null
+/*
+ * Copyright 2011 Electronic Business Systems Ltd.
+ *
+ * This file is part of GSS.
+ *
+ * GSS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GSS. If not, see <http://www.gnu.org/licenses/>.
+ */
+package gr.ebs.gss.server.webdav.milton;
+
+import static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration;
+import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
+import gr.ebs.gss.client.exceptions.RpcException;
+import gr.ebs.gss.server.domain.User;
+import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
+import gr.ebs.gss.server.domain.dto.FolderDTO;
+import gr.ebs.gss.server.domain.dto.UserDTO;
+import gr.ebs.gss.server.ejb.ExternalAPI;
+import gr.ebs.gss.server.ejb.TransactionHelper;
+
+import java.util.Date;
+import java.util.concurrent.Callable;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.rmi.PortableRemoteObject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.bradmcevoy.http.HttpManager;
+import com.bradmcevoy.http.Resource;
+import com.bradmcevoy.http.ResourceFactory;
+import com.bradmcevoy.http.SecurityManager;
+import com.ettrema.http.fs.LockManager;
+
+
+/**
+ * @author kman
+ *
+ */
+public class GSSResourceFactory implements ResourceFactory {
+ private static final Logger log = LoggerFactory.getLogger(GSSResourceFactory.class);
+
+ SecurityManager securityManager;
+ LockManager lockManager;
+ Long maxAgeSeconds;
+ String contextPath;
+ boolean allowDirectoryBrowsing;
+ String defaultPage;
+ HttpManager httpManager;
+ @Override
+ public Resource getResource(String host, String url) {
+ log.debug("getResource: host: " + host + " - url:" + url);
+ url = stripContext(url);
+ if(url==null||url.trim().equals(""))
+ url="/";
+ try {
+
+ Object r = getResourceGss(url);
+ if(r==null)
+ return null;
+ if(r instanceof FolderDTO)
+ return new GssFolderResource(host, this,r );
+ else
+ return new GssFileResource(host, this,r);
+ } catch (RpcException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ public Long maxAgeSeconds(GssResource resource) {
+ return maxAgeSeconds;
+ }
+ private Object getResourceGss(String path) throws RpcException{
+ UserDTO user = getService().getUserByUserName("past@ebs.gr");
+ boolean exists = true;
+ Object resource = null;
+ FileHeaderDTO file = null;
+ FolderDTO folder = null;
+ try {
+ resource = getService().getResourceAtPath(user.getId(), path, true);
+ } catch (ObjectNotFoundException e) {
+ exists = false;
+ } catch (RpcException e) {
+
+ return null;
+ }
+
+ if (!exists) {
+
+ return null;
+ }
+
+ return resource;
+ }
+
+
+ private String stripContext( String url ) {
+ if( this.contextPath != null && contextPath.length() > 0 ) {
+ url = url.replaceFirst( '/' + contextPath, "");
+ log.debug( "stripped context: " + url);
+ return url;
+ } else {
+ return url;
+ }
+ }
+
+ /**
+ * For a provided path, remove the last element and return the rest, that is
+ * the path of the parent folder.
+ *
+ * @param path the specified path
+ * @return the path of the parent folder
+ * @throws ObjectNotFoundException if the provided string contains no path
+ * delimiters
+ */
+ protected String getParentPath(String path) throws ObjectNotFoundException {
+ int lastDelimiter = path.lastIndexOf('/');
+ if (lastDelimiter == 0)
+ return "/";
+ if (lastDelimiter == -1)
+ // No path found.
+ throw new ObjectNotFoundException("There is no parent in the path: " + path);
+ else if (lastDelimiter < path.length() - 1)
+ // Return the part before the delimiter.
+ return path.substring(0, lastDelimiter);
+ else {
+ // Remove the trailing delimiter and then recurse.
+ String strippedTrail = path.substring(0, lastDelimiter);
+ return getParentPath(strippedTrail);
+ }
+ }
+
+ /**
+ * A helper method that retrieves a reference to the ExternalAPI bean and
+ * stores it for future use.
+ *
+ * @return an ExternalAPI instance
+ * @throws RpcException in case an error occurs
+ */
+ protected ExternalAPI getService() throws RpcException {
+ try {
+ final Context ctx = new InitialContext();
+ final Object ref = ctx.lookup(getConfiguration().getString("externalApiPath"));
+ return (ExternalAPI) PortableRemoteObject.narrow(ref, ExternalAPI.class);
+ } catch (final NamingException e) {
+ log.error("Unable to retrieve the ExternalAPI EJB", e);
+ throw new RpcException("An error occurred while contacting the naming service");
+ }
+ }
+
+ private void updateAccounting(final User user, final Date date, final long bandwidthDiff) {
+ try {
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().updateAccounting(user, date, bandwidthDiff);
+ return null;
+ }
+ });
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ // updateAccounting() doesn't throw any checked exceptions
+ assert false;
+ }
+ }
+
+
+ /**
+ * Retrieve the securityManager.
+ *
+ * @return the securityManager
+ */
+ public SecurityManager getSecurityManager() {
+ return securityManager;
+ }
+
+
+ /**
+ * Retrieve the lockManager.
+ *
+ * @return the lockManager
+ */
+ public LockManager getLockManager() {
+ return lockManager;
+ }
+
+
+ /**
+ * Retrieve the maxAgeSeconds.
+ *
+ * @return the maxAgeSeconds
+ */
+ public Long getMaxAgeSeconds() {
+ return maxAgeSeconds;
+ }
+
+
+ /**
+ * Retrieve the contextPath.
+ *
+ * @return the contextPath
+ */
+ public String getContextPath() {
+ return contextPath;
+ }
+
+
+ /**
+ * Retrieve the allowDirectoryBrowsing.
+ *
+ * @return the allowDirectoryBrowsing
+ */
+ public boolean isAllowDirectoryBrowsing() {
+ return allowDirectoryBrowsing;
+ }
+
+
+ /**
+ * Retrieve the defaultPage.
+ *
+ * @return the defaultPage
+ */
+ public String getDefaultPage() {
+ return defaultPage;
+ }
+
+ public String getRealm(String host) {
+ return securityManager.getRealm(host);
+ }
+
+
+ /**
+ * Modify the securityManager.
+ *
+ * @param securityManager the securityManager to set
+ */
+ public void setSecurityManager(SecurityManager securityManager) {
+ this.securityManager = securityManager;
+ }
+
+
+ /**
+ * Modify the lockManager.
+ *
+ * @param lockManager the lockManager to set
+ */
+ public void setLockManager(LockManager lockManager) {
+ this.lockManager = lockManager;
+ }
+
+
+ /**
+ * Modify the maxAgeSeconds.
+ *
+ * @param maxAgeSeconds the maxAgeSeconds to set
+ */
+ public void setMaxAgeSeconds(Long maxAgeSeconds) {
+ this.maxAgeSeconds = maxAgeSeconds;
+ }
+
+
+ /**
+ * Modify the contextPath.
+ *
+ * @param contextPath the contextPath to set
+ */
+ public void setContextPath(String contextPath) {
+ this.contextPath = contextPath;
+ }
+
+
+ /**
+ * Modify the defaultPage.
+ *
+ * @param defaultPage the defaultPage to set
+ */
+ public void setDefaultPage(String defaultPage) {
+ this.defaultPage = defaultPage;
+ }
+
+
+ /**
+ * Retrieve the httpManager.
+ *
+ * @return the httpManager
+ */
+ public HttpManager getHttpManager() {
+ return httpManager;
+ }
+
+
+ /**
+ * Modify the httpManager.
+ *
+ * @param httpManager the httpManager to set
+ */
+ public void setHttpManager(HttpManager httpManager) {
+ this.httpManager = httpManager;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2011 Electronic Business Systems Ltd.
+ *
+ * This file is part of GSS.
+ *
+ * GSS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GSS. If not, see <http://www.gnu.org/licenses/>.
+ */
+package gr.ebs.gss.server.webdav.milton;
+
+import java.util.List;
+
+import com.bradmcevoy.http.AuthenticationHandler;
+
+
+/**
+ * @author kman
+ *
+ */
+public class GssAuthenticationService extends com.bradmcevoy.http.AuthenticationService{
+
+ public GssAuthenticationService( List<AuthenticationHandler> authenticationHandlers ) {
+ super(authenticationHandlers);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2011 Electronic Business Systems Ltd.
+ *
+ * This file is part of GSS.
+ *
+ * GSS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GSS. If not, see <http://www.gnu.org/licenses/>.
+ */
+package gr.ebs.gss.server.webdav.milton;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.bradmcevoy.common.ContentTypeUtils;
+import com.bradmcevoy.http.Auth;
+import com.bradmcevoy.http.CollectionResource;
+import com.bradmcevoy.http.CopyableResource;
+import com.bradmcevoy.http.DeletableResource;
+import com.bradmcevoy.http.GetableResource;
+import com.bradmcevoy.http.MoveableResource;
+import com.bradmcevoy.http.PropFindableResource;
+import com.bradmcevoy.http.PropPatchableResource;
+import com.bradmcevoy.http.Range;
+import com.bradmcevoy.http.Request;
+import com.bradmcevoy.http.exceptions.BadRequestException;
+import com.bradmcevoy.http.exceptions.ConflictException;
+import com.bradmcevoy.http.exceptions.NotAuthorizedException;
+import com.bradmcevoy.http.webdav.PropPatchHandler.Fields;
+
+import gr.ebs.gss.client.exceptions.DuplicateNameException;
+import gr.ebs.gss.client.exceptions.GSSIOException;
+import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
+import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
+import gr.ebs.gss.client.exceptions.RpcException;
+import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
+import gr.ebs.gss.server.domain.dto.UserDTO;
+import gr.ebs.gss.server.ejb.TransactionHelper;
+
+
+/**
+ * @author kman
+ *
+ */
+public class GssFileResource extends GssResource implements CopyableResource, DeletableResource, GetableResource, MoveableResource, PropFindableResource, PropPatchableResource {
+ FileHeaderDTO file;
+ private static final Logger log = LoggerFactory.getLogger(GssFileResource.class);
+ /**
+ * @param host
+ * @param factory
+ * @param resource
+ */
+ public GssFileResource(String host, GSSResourceFactory factory, Object resource) {
+ super(host, factory, resource);
+ this.file = (FileHeaderDTO)resource;
+
+ }
+ @Override
+ public String checkRedirect(Request arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public Date getModifiedDate() {
+ return file.getAuditInfo().getModificationDate();
+ }
+ @Override
+ public String getName() {
+ return file.getName();
+ }
+ @Override
+ public String getUniqueId() {
+ return "file:"+file.getId().toString();
+ }
+ @Override
+ public void moveTo(final CollectionResource newParent, final String arg1) throws ConflictException, NotAuthorizedException, BadRequestException {
+ if( newParent instanceof GssFolderResource ) {
+ final GssFolderResource newFsParent = (GssFolderResource) newParent;
+ try {
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+
+ @Override
+ public Void call() throws Exception {
+ factory.getService().moveFile(getCurrentUser().getId(), file.getId(), newFsParent.folder.getId(), arg1);
+ return null;
+ }
+
+ });
+ GssFileResource.this.file = factory.getService().getFile(getCurrentUser().getId(), file.getId());
+
+ } catch (InsufficientPermissionsException e) {
+ throw new NotAuthorizedException(this);
+ } catch (ObjectNotFoundException e) {
+ throw new BadRequestException(this);
+ } catch (DuplicateNameException e) {
+ throw new ConflictException(this);
+ } catch (RpcException e) {
+ throw new RuntimeException("System error");
+ } catch (GSSIOException e) {
+ throw new RuntimeException("Unable to Move");
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to Move");
+ }
+ } else {
+ throw new RuntimeException("Destination is an unknown type. Must be a Folder, is a: " + newParent.getClass());
+ }
+
+ }
+ @Override
+ public void copyTo(final CollectionResource newParent, final String arg1) throws NotAuthorizedException, BadRequestException, ConflictException {
+ if( newParent instanceof GssFolderResource ) {
+ final GssFolderResource newFsParent = (GssFolderResource) newParent;
+ try {
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+
+ @Override
+ public Void call() throws Exception {
+ factory.getService().copyFile(getCurrentUser().getId(), file.getId(), newFsParent.folder.getId(), arg1);
+ return null;
+ }
+
+ });
+ GssFileResource.this.file = factory.getService().getFile(getCurrentUser().getId(), file.getId());
+ } catch (InsufficientPermissionsException e) {
+ throw new NotAuthorizedException(this);
+ } catch (ObjectNotFoundException e) {
+ throw new BadRequestException(this);
+ } catch (DuplicateNameException e) {
+ throw new ConflictException(this);
+ } catch (RpcException e) {
+ throw new RuntimeException("System error");
+ } catch (GSSIOException e) {
+ throw new RuntimeException("Unable to Move");
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to Move");
+ }
+ } else {
+ throw new RuntimeException("Destination is an unknown type. Must be a FsDirectoryResource, is a: " + newParent.getClass());
+ }
+
+ }
+ @Override
+ public void delete() throws NotAuthorizedException, ConflictException, BadRequestException {
+ try {
+ factory.getService().deleteFile(getCurrentUser().getId(), file.getId());
+ } catch (ObjectNotFoundException e) {
+ throw new BadRequestException(this);
+ } catch (InsufficientPermissionsException e) {
+ throw new NotAuthorizedException(this);
+ } catch (RpcException e) {
+ throw new BadRequestException(this);
+ }
+
+ }
+ @Override
+ public Long getContentLength() {
+ return file.getFileSize();
+ }
+ @Override
+ public String getContentType(String preferredList ) {
+ return file.getMimeType();
+ }
+ @Override
+ public Long getMaxAgeSeconds(Auth arg0) {
+ return factory.maxAgeSeconds( this );
+ }
+ @Override
+ public void sendContent(OutputStream out, Range range, Map<String, String> params, String contentType ) throws IOException {
+ InputStream in = null;
+ try {
+ in = factory.getService().getFileContents(getCurrentUser().getId(), file.getId());
+ // if( range != null ) {
+ // long start = range.getStart();
+ // if( start > 0 ) in.skip(start);
+ // long finish = range.getFinish();
+ // if( finish > 0 ) {
+ // StreamToStream.readTo(in, out);
+ // }
+ // } else {
+ int bytes = IOUtils.copy( in, out );
+
+ out.flush();
+ // }
+ } catch (ObjectNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InsufficientPermissionsException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (RpcException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } finally {
+ IOUtils.closeQuietly( in );
+ }
+
+ }
+ @Override
+ public Date getCreateDate() {
+ // TODO Auto-generated method stub
+ return file.getAuditInfo().getCreationDate();
+ }
+ @Override
+ public void setProperties(Fields arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2011 Electronic Business Systems Ltd.
+ *
+ * This file is part of GSS.
+ *
+ * GSS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GSS. If not, see <http://www.gnu.org/licenses/>.
+ */
+package gr.ebs.gss.server.webdav.milton;
+
+import gr.ebs.gss.client.exceptions.DuplicateNameException;
+import gr.ebs.gss.client.exceptions.GSSIOException;
+import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
+import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
+import gr.ebs.gss.client.exceptions.QuotaExceededException;
+import gr.ebs.gss.client.exceptions.RpcException;
+import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
+import gr.ebs.gss.server.domain.dto.FolderDTO;
+import gr.ebs.gss.server.ejb.TransactionHelper;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.bradmcevoy.http.Auth;
+import com.bradmcevoy.http.CollectionResource;
+import com.bradmcevoy.http.CopyableResource;
+import com.bradmcevoy.http.DeletableResource;
+import com.bradmcevoy.http.GetableResource;
+import com.bradmcevoy.http.LockInfo;
+import com.bradmcevoy.http.LockResult;
+import com.bradmcevoy.http.LockTimeout;
+import com.bradmcevoy.http.LockToken;
+import com.bradmcevoy.http.LockingCollectionResource;
+import com.bradmcevoy.http.MakeCollectionableResource;
+import com.bradmcevoy.http.MoveableResource;
+import com.bradmcevoy.http.PropFindableResource;
+import com.bradmcevoy.http.PutableResource;
+import com.bradmcevoy.http.Range;
+import com.bradmcevoy.http.Request;
+import com.bradmcevoy.http.Resource;
+import com.bradmcevoy.http.XmlWriter;
+import com.bradmcevoy.http.exceptions.BadRequestException;
+import com.bradmcevoy.http.exceptions.ConflictException;
+import com.bradmcevoy.http.exceptions.NotAuthorizedException;
+
+
+/**
+ * @author kman
+ *
+ */
+public class GssFolderResource extends GssResource implements MakeCollectionableResource, PutableResource, CopyableResource, DeletableResource, MoveableResource, PropFindableResource, LockingCollectionResource, GetableResource{
+ private static final Logger log = LoggerFactory.getLogger(GssFolderResource.class);
+ FolderDTO folder;
+
+ /**
+ * @param host
+ * @param factory
+ * @param resource
+ */
+ public GssFolderResource(String host, GSSResourceFactory factory, Object resource) {
+ super(host, factory, resource);
+ folder=(FolderDTO) resource;
+ }
+ @Override
+ public String checkRedirect(Request request) {
+ if( factory.getDefaultPage() != null ) {
+ return request.getAbsoluteUrl() + "/" + factory.getDefaultPage();
+ } else {
+ return null;
+ }
+ }
+ @Override
+ public Date getModifiedDate() {
+ return folder.getAuditInfo().getModificationDate();
+ }
+ @Override
+ public String getName() {
+ return folder.getName();
+ }
+ @Override
+ public String getUniqueId() {
+ return "folder:"+folder.getId().toString();
+ }
+ @Override
+ public void moveTo(final CollectionResource newParent, final String arg1) throws ConflictException, NotAuthorizedException, BadRequestException {
+ if( newParent instanceof GssFolderResource ) {
+ final GssFolderResource newFsParent = (GssFolderResource) newParent;
+ try {
+ if(newFsParent.folder.getName().equals(folder.getParent().getName())){
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+
+ @Override
+ public Void call() throws Exception {
+ factory.getService().updateFolder(getCurrentUser().getId(), folder.getId(), arg1, null, null);
+ return null;
+ }
+
+ });
+ }
+ else new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+
+ @Override
+ public Void call() throws Exception {
+ factory.getService().moveFolder(getCurrentUser().getId(), folder.getId(), newFsParent.folder.getId(), arg1);
+ log.info("MOVING OK:"+arg1);
+
+ return null;
+ }
+
+ });
+ GssFolderResource.this.folder = factory.getService().getFolder(getCurrentUser().getId(), folder.getId());
+ log.info("MOVING:"+folder.getName());
+
+ } catch (InsufficientPermissionsException e) {
+ throw new NotAuthorizedException(this);
+ } catch (ObjectNotFoundException e) {
+ throw new BadRequestException(this);
+ } catch (DuplicateNameException e) {
+ throw new ConflictException(this);
+ } catch (RpcException e) {
+ throw new RuntimeException("System error");
+ } catch (GSSIOException e) {
+ throw new RuntimeException("Unable to Move");
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to Move");
+ }
+ } else {
+ throw new RuntimeException("Destination is an unknown type. Must be a Folder, is a: " + newParent.getClass());
+ }
+
+ }
+ @Override
+ public void copyTo(final CollectionResource newParent, final String arg1) throws NotAuthorizedException, BadRequestException, ConflictException {
+ if( newParent instanceof GssFolderResource ) {
+ final GssFolderResource newFsParent = (GssFolderResource) newParent;
+ try {
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+
+ @Override
+ public Void call() throws Exception {
+ factory.getService().copyFolder(getCurrentUser().getId(), folder.getId(), newFsParent.folder.getId(), arg1);
+ return null;
+ }
+
+ });
+ GssFolderResource.this.folder = factory.getService().getFolder(getCurrentUser().getId(), folder.getId());
+ } catch (InsufficientPermissionsException e) {
+ throw new NotAuthorizedException(this);
+ } catch (ObjectNotFoundException e) {
+ throw new BadRequestException(this);
+ } catch (DuplicateNameException e) {
+ throw new ConflictException(this);
+ } catch (RpcException e) {
+ throw new RuntimeException("System error");
+ } catch (GSSIOException e) {
+ throw new RuntimeException("Unable to Move");
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to Move");
+ }
+ } else {
+ throw new RuntimeException("Destination is an unknown type. Must be a FsDirectoryResource, is a: " + newParent.getClass());
+ }
+
+ }
+ @Override
+ public CollectionResource createCollection(final String name) throws NotAuthorizedException, ConflictException, BadRequestException {
+ try {
+ final FolderDTO folderParent = folder;
+ FolderDTO created = new TransactionHelper<FolderDTO>().tryExecute(new Callable<FolderDTO>() {
+ @Override
+ public FolderDTO call() throws Exception {
+ FolderDTO f = factory.getService().createFolder(getCurrentUser().getId(), folder.getId(), name);
+ return f;
+ }
+ });
+ return new GssFolderResource(host, factory, created);
+ } catch (DuplicateNameException e) {
+ e.printStackTrace();
+ // XXX If the existing name is a folder we should be returning
+ // SC_METHOD_NOT_ALLOWED, or even better, just do the createFolder
+ // without checking first and then deal with the exceptions.
+ throw new ConflictException(this);
+ } catch (InsufficientPermissionsException e) {
+ e.printStackTrace();
+ throw new NotAuthorizedException(this);
+ } catch (ObjectNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ } catch (RpcException e) {
+ e.printStackTrace();
+ throw new RuntimeException("System Error");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("System Error");
+ }
+ }
+ @Override
+ public Resource child(String name) {
+ for(FolderDTO f : folder.getSubfolders())
+ if(f.getName().equals(name))
+ return new GssFolderResource(host, factory, f);
+
+ try {
+ for(FileHeaderDTO f : factory.getService().getFiles(folder.getOwner().getId(), folder.getId(), true))
+ if(f.getName().equals(name))
+ return new GssFileResource(host, factory, f);
+ } catch (ObjectNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InsufficientPermissionsException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (RpcException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+ @Override
+ public List<? extends Resource> getChildren() {
+ try {
+ this.folder = factory.getService().getFolder(getCurrentUser().getId(), folder.getId());
+ } catch (ObjectNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InsufficientPermissionsException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (RpcException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ List<GssResource> result = new ArrayList<GssResource>();
+ for(FolderDTO f : folder.getSubfolders())
+ if(!f.isDeleted())
+ result.add(new GssFolderResource(host, factory, f));
+ try {
+ for(FileHeaderDTO f : factory.getService().getFiles(getCurrentUser().getId(), folder.getId(), true))
+ result.add(new GssFileResource(host, factory, f));
+ } catch (ObjectNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InsufficientPermissionsException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (RpcException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return result;
+ }
+ @Override
+ public Resource createNew(final String name, InputStream in, Long length, final String contentType ) throws IOException, ConflictException, NotAuthorizedException, BadRequestException {
+
+ File uploadedFile = null;
+ try {
+ uploadedFile = factory.getService().uploadFile(in, getCurrentUser().getId());
+ } catch (IOException ex) {
+ throw new IOException(ex);
+ } catch (ObjectNotFoundException e) {
+ e.printStackTrace();
+ throw new BadRequestException(this);
+ } catch (RpcException e) {
+ throw new RuntimeException("Unable to upload file");
+ }
+ final File uf = uploadedFile;
+ try {
+ String pathFolder = folder.getPath();
+ if(!pathFolder.endsWith("/"))
+ pathFolder=pathFolder+"/";
+ String fname = pathFolder+name;
+ Object ff2;
+ try{
+ ff2 = factory.getService().getResourceAtPath(folder.getOwner().getId(), fname, true);
+ }
+ catch(ObjectNotFoundException ex){
+ ff2=null;
+ }
+ final Object ff = ff2;
+ FileHeaderDTO kmfileDTO=null;
+ if(ff!=null && ff instanceof FileHeaderDTO){
+ kmfileDTO = new TransactionHelper<FileHeaderDTO>().tryExecute(new Callable<FileHeaderDTO>() {
+ @Override
+ public FileHeaderDTO call() throws Exception{
+ return factory.getService().updateFileContents(getCurrentUser().getId(), ((FileHeaderDTO)ff).getId(), contentType, uf.length(), uf.getAbsolutePath());
+ }
+ });
+ }
+ else
+ kmfileDTO = new TransactionHelper<FileHeaderDTO>().tryExecute(new Callable<FileHeaderDTO>() {
+ @Override
+ public FileHeaderDTO call() throws Exception{
+ return factory.getService().createFile(getCurrentUser().getId(), folder.getId(), name, contentType, uf.length(), uf.getAbsolutePath());
+ }
+ });
+ return new GssFileResource(host, factory, kmfileDTO);
+ } catch (ObjectNotFoundException e) {
+ throw new BadRequestException(this);
+ } catch (InsufficientPermissionsException e) {
+ throw new NotAuthorizedException(this);
+ }
+ catch (DuplicateNameException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ throw new ConflictException(this);
+ }
+ catch(QuotaExceededException e){
+ throw new ConflictException(this);
+ }
+ catch(Exception e){
+ throw new RuntimeException("System Error");
+ }
+ }
+ @Override
+ public void delete() throws NotAuthorizedException, ConflictException, BadRequestException {
+ try {
+ factory.getService().deleteFolder(getCurrentUser().getId(), folder.getId());
+ } catch (InsufficientPermissionsException e) {
+ e.printStackTrace();
+ throw new NotAuthorizedException(this);
+ } catch (ObjectNotFoundException e) {
+ e.printStackTrace();
+ throw new BadRequestException(this);
+ } catch (RpcException e) {
+ e.printStackTrace();
+ throw new BadRequestException(this);
+ }
+
+ }
+ @Override
+ public Date getCreateDate() {
+ if(folder!=null && folder.getAuditInfo()!=null)
+ return folder.getAuditInfo().getCreationDate();
+ return null;
+ }
+ @Override
+ public LockToken createAndLock(final String name, LockTimeout timeout, LockInfo lockInfo ) throws NotAuthorizedException {
+ log.info("CREATE AND LOCK");
+ final File tmp = new File("/tmp/"+new java.util.Random().nextInt());
+ FileHeaderDTO kmfileDTO=null;
+ try {
+ kmfileDTO = new TransactionHelper<FileHeaderDTO>().tryExecute(new Callable<FileHeaderDTO>() {
+ @Override
+ public FileHeaderDTO call() throws Exception {
+ return factory.getService().createFile(getCurrentUser().getId(), folder.getId(), name, "text/html", tmp.length(), tmp.getAbsolutePath());
+ }
+ });
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ log.info("CREATE AND LOCK:"+kmfileDTO.getId());
+ //File dest = new File( this.getFile(), name );
+ //createEmptyFile( );
+ GssFileResource newRes = new GssFileResource( host, factory, kmfileDTO );
+ LockResult res = newRes.lock( timeout, lockInfo );
+ return res.getLockToken();
+
+ }
+ @Override
+ public Long getContentLength() {
+ return null;
+ }
+ @Override
+ public String getContentType(String arg0) {
+ return "text/html";
+ }
+ @Override
+ public Long getMaxAgeSeconds(Auth arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ /**
+ * Will generate a listing of the contents of this directory, unless
+ * the factory's allowDirectoryBrowsing has been set to false.
+ *
+ * If so it will just output a message saying that access has been disabled.
+ *
+ * @param out
+ * @param range
+ * @param params
+ * @param contentType
+ * @throws IOException
+ * @throws NotAuthorizedException
+ */
+ public void sendContent( OutputStream out, Range range, Map<String, String> params, String contentType ) throws IOException, NotAuthorizedException {
+ String subpath = folder.getPath();//getFile().getCanonicalPath().substring( factory.getRoot().getCanonicalPath().length() ).replace( '\\', '/' );
+ String uri = "/" + factory.getContextPath() + subpath;
+ XmlWriter w = new XmlWriter( out );
+ w.open( "html" );
+ w.open( "body" );
+ w.begin( "h1" ).open().writeText( this.getName() ).close();
+ w.open( "table" );
+ for( Resource r : getChildren() ) {
+ w.open( "tr" );
+
+ w.open( "td" );
+ w.begin( "a" ).writeAtt( "href", uri + "/" + r.getName() ).open().writeText( r.getName() ).close();
+ w.close( "td" );
+
+ w.begin( "td" ).open().writeText( r.getModifiedDate() + "" ).close();
+ w.close( "tr" );
+ }
+ w.close( "table" );
+ w.close( "body" );
+ w.close( "html" );
+ w.flush();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2011 Electronic Business Systems Ltd.
+ *
+ * This file is part of GSS.
+ *
+ * GSS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GSS. If not, see <http://www.gnu.org/licenses/>.
+ */
+package gr.ebs.gss.server.webdav.milton;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.bradmcevoy.http.LockInfo;
+import com.bradmcevoy.http.LockResult;
+import com.bradmcevoy.http.LockTimeout;
+import com.bradmcevoy.http.LockToken;
+import com.bradmcevoy.http.LockableResource;
+import com.bradmcevoy.http.exceptions.NotAuthorizedException;
+import com.ettrema.http.fs.LockManager;
+
+
+/**
+ * @author kman
+ *
+ */
+public class GssMemoryLockManager implements LockManager {
+
+ private static final Logger log = LoggerFactory.getLogger( GssMemoryLockManager.class );
+ /**
+ * maps current locks by the file associated with the resource
+ */
+ Map<String, CurrentLock> locksByFile;
+ Map<String, CurrentLock> locksByToken;
+
+ public GssMemoryLockManager() {
+ locksByFile = new HashMap<String, CurrentLock>();
+ locksByToken = new HashMap<String, CurrentLock>();
+ }
+
+ public synchronized LockResult lock( LockTimeout timeout, LockInfo lockInfo, LockableResource r ) {
+ GssResource resource = (GssResource) r;
+ LockToken currentLock = currentLock( resource );
+ if( currentLock != null ) {
+ return LockResult.failed( LockResult.FailureReason.ALREADY_LOCKED );
+ }
+
+ LockToken newToken = new LockToken( UUID.randomUUID().toString(), lockInfo, timeout );
+ CurrentLock newLock = new CurrentLock( resource.getUniqueId(), newToken, lockInfo.lockedByUser );
+ locksByFile.put( resource.getUniqueId(), newLock );
+ locksByToken.put( newToken.tokenId, newLock );
+ return LockResult.success( newToken );
+ }
+
+ public synchronized LockResult refresh( String tokenId, LockableResource resource ) {
+ CurrentLock curLock = locksByToken.get( tokenId );
+ if( curLock == null ) {
+ log.debug( "can't refresh because no lock");
+ return LockResult.failed( LockResult.FailureReason.PRECONDITION_FAILED );
+ } else {
+ curLock.token.setFrom( new Date() );
+ return LockResult.success( curLock.token );
+ }
+ }
+
+ public synchronized void unlock( String tokenId, LockableResource r ) throws NotAuthorizedException {
+ GssResource resource = (GssResource) r;
+ LockToken lockToken = currentLock( resource );
+ if( lockToken == null ) {
+ log.debug( "not locked" );
+ return;
+ }
+ if( lockToken.tokenId.equals( tokenId ) ) {
+ removeLock( lockToken );
+ } else {
+ throw new NotAuthorizedException( resource );
+ }
+ }
+
+ private LockToken currentLock( GssResource resource ) {
+ CurrentLock curLock = locksByFile.get( resource.getUniqueId() );
+ if( curLock == null ) return null;
+ LockToken token = curLock.token;
+ if( token.isExpired() ) {
+ removeLock( token );
+ return null;
+ } else {
+ return token;
+ }
+ }
+
+ private void removeLock( LockToken token ) {
+ log.debug( "removeLock: " + token.tokenId );
+ CurrentLock currentLock = locksByToken.get( token.tokenId );
+ if( currentLock != null ) {
+ locksByFile.remove( currentLock.file );
+ locksByToken.remove( currentLock.token.tokenId );
+ } else {
+ log.warn( "couldnt find lock: " + token.tokenId );
+ }
+ }
+
+ public LockToken getCurrentToken( LockableResource r ) {
+ GssResource resource = (GssResource) r;
+ CurrentLock lock = locksByFile.get( resource.getUniqueId() );
+ if( lock == null ) return null;
+ LockToken token = new LockToken();
+ token.info = new LockInfo( LockInfo.LockScope.EXCLUSIVE, LockInfo.LockType.WRITE, lock.lockedByUser, LockInfo.LockDepth.ZERO );
+ token.info.lockedByUser = lock.lockedByUser;
+ token.timeout = lock.token.timeout;
+ token.tokenId = lock.token.tokenId;
+ return token;
+ }
+
+ class CurrentLock {
+
+ final String file;
+ final LockToken token;
+ final String lockedByUser;
+
+ public CurrentLock( String file, LockToken token, String lockedByUser ) {
+ this.file = file;
+ this.token = token;
+ this.lockedByUser = lockedByUser;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2011 Electronic Business Systems Ltd.
+ *
+ * This file is part of GSS.
+ *
+ * GSS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GSS. If not, see <http://www.gnu.org/licenses/>.
+ */
+package gr.ebs.gss.server.webdav.milton;
+
+import gr.ebs.gss.server.domain.User;
+import gr.ebs.gss.server.domain.dto.UserDTO;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.bradmcevoy.http.Auth;
+import com.bradmcevoy.http.CopyableResource;
+import com.bradmcevoy.http.DigestResource;
+import com.bradmcevoy.http.HttpManager;
+import com.bradmcevoy.http.LockInfo;
+import com.bradmcevoy.http.LockResult;
+import com.bradmcevoy.http.LockTimeout;
+import com.bradmcevoy.http.LockToken;
+import com.bradmcevoy.http.LockableResource;
+import com.bradmcevoy.http.MoveableResource;
+import com.bradmcevoy.http.Request;
+import com.bradmcevoy.http.Resource;
+import com.bradmcevoy.http.Request.Method;
+import com.bradmcevoy.http.exceptions.NotAuthorizedException;
+import com.bradmcevoy.http.http11.auth.DigestResponse;
+
+
+/**
+ * @author kman
+ *
+ */
+public abstract class GssResource implements Resource, MoveableResource, CopyableResource, LockableResource, DigestResource {
+ private static final Logger log = LoggerFactory.getLogger(GssResource.class);
+ String host;
+ GSSResourceFactory factory;
+ Object resource;
+ UserDTO currentUser;
+
+ /**
+ *
+ */
+ public GssResource(String host, GSSResourceFactory factory, Object resource) {
+ this.host=host;
+ this.factory=factory;
+ this.resource=resource;
+ this.currentUser=currentUser;
+ }
+
+ public Object authenticate(String user, String password) {
+ return factory.getSecurityManager().authenticate(user, password);
+ }
+
+ public Object authenticate( DigestResponse digestRequest ) {
+ currentUser = (UserDTO) factory.getSecurityManager().authenticate(digestRequest);
+ return currentUser;
+
+ }
+
+ public boolean isDigestAllowed() {
+ return true;
+ }
+
+
+
+
+ public boolean authorise(Request request, Method method, Auth auth) {
+ return factory.getSecurityManager().authorise(request, method, auth, this);
+ }
+
+ public String getRealm() {
+ return factory.getRealm(this.host);
+ }
+
+ public LockResult lock(LockTimeout timeout, LockInfo lockInfo) throws NotAuthorizedException {
+ return factory.getLockManager().lock(timeout, lockInfo, this);
+ }
+
+ public LockResult refreshLock(String token) throws NotAuthorizedException {
+ return factory.getLockManager().refresh(token, this);
+ }
+
+ public void unlock(String tokenId) throws NotAuthorizedException {
+ factory.getLockManager().unlock(tokenId, this);
+ }
+
+ public LockToken getCurrentLock() {
+ if( factory.getLockManager() != null ) {
+ return factory.getLockManager().getCurrentToken( this );
+ } else {
+ log.warn("getCurrentLock called, but no lock manager: file: " + resource);
+ return null;
+ }
+ }
+
+
+ /**
+ * Retrieve the currentUser.
+ *
+ * @return the currentUser
+ */
+ public UserDTO getCurrentUser() {
+ return currentUser;
+ }
+
+
+}
--- /dev/null
+/*
+ * Copyright 2011 Electronic Business Systems Ltd.
+ *
+ * This file is part of GSS.
+ *
+ * GSS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GSS. If not, see <http://www.gnu.org/licenses/>.
+ */
+package gr.ebs.gss.server.webdav.milton;
+
+import static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration;
+import gr.ebs.gss.client.exceptions.RpcException;
+import gr.ebs.gss.server.domain.User;
+import gr.ebs.gss.server.ejb.ExternalAPI;
+import gr.ebs.gss.server.ejb.TransactionHelper;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.rmi.PortableRemoteObject;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+
+import org.apache.commons.codec.binary.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.bradmcevoy.http.Auth;
+import com.bradmcevoy.http.Request;
+import com.bradmcevoy.http.Resource;
+import com.bradmcevoy.http.Request.Method;
+import com.bradmcevoy.http.http11.auth.DigestGenerator;
+import com.bradmcevoy.http.http11.auth.DigestResponse;
+import com.ettrema.http.fs.SimpleSecurityManager;
+
+
+/**
+ * @author kman
+ *
+ */
+public class GssSecurityManager implements com.bradmcevoy.http.SecurityManager{
+
+ private static final Logger log = LoggerFactory.getLogger(SimpleSecurityManager.class);
+
+ private String realm;
+ private DigestGenerator digestGenerator;
+
+ public GssSecurityManager() {
+ digestGenerator = new DigestGenerator();
+ }
+
+ public GssSecurityManager( DigestGenerator digestGenerator ) {
+ this.digestGenerator = digestGenerator;
+ }
+
+
+ public GssSecurityManager( String realm) {
+ this.realm = realm;
+
+ }
+ /*
+ public Object getUserByName( String name ) {
+ String actualPassword = nameAndPasswords.get( name );
+ if( actualPassword != null ) return name;
+ return null;
+ }*/
+
+
+
+ public Object authenticate( String user, String password ) {
+ log.debug( "authenticate: " + user + " - " + password);
+ // user name will include domain when coming form ftp. we just strip it off
+ if( user.contains( "@")) {
+ user = user.substring( 0, user.indexOf( "@"));
+ }
+ String actualPassword=null;
+ try {
+ actualPassword = getUsersPassword( user );
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ if( actualPassword == null ) {
+ log.debug( "user not found: " + user);
+ return null;
+ } else {
+ boolean ok;
+ if( actualPassword == null ) {
+ ok = password == null || password.length()==0;
+ } else {
+ ok = actualPassword.equals( password);
+ }
+ return ok ? user : null;
+ }
+ }
+
+ public Object authenticate( DigestResponse digestRequest ) {
+ String actualPassword=null;
+ try {
+ actualPassword = getUsersPassword( digestRequest.getUser() );
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+
+ String serverResponse = digestGenerator.generateDigest( digestRequest, actualPassword );
+ String clientResponse = digestRequest.getResponseDigest();
+
+ if( serverResponse.equals( clientResponse ) ) {
+ try {
+ return getService().getUserByUserName(digestRequest.getUser());
+ } catch (RpcException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+
+
+ public boolean authorise( Request request, Method method, Auth auth, Resource resource ) {
+ return auth != null && auth.getTag() != null;
+ }
+
+ public String getRealm(String host) {
+ return realm;
+ }
+
+ /**
+ * @param realm the realm to set
+ */
+ public void setRealm( String realm ) {
+ this.realm = realm;
+ }
+
+ private ExternalAPI getService() throws RpcException {
+ try {
+ final Context ctx = new InitialContext();
+ final Object ref = ctx.lookup(getConfiguration().getString("externalApiPath"));
+ return (ExternalAPI) PortableRemoteObject.narrow(ref, ExternalAPI.class);
+ } catch (final NamingException e) {
+ log.error("Unable to retrieve the ExternalAPI EJB", e);
+ throw new RpcException("An error occurred while contacting the naming service");
+ }
+ }
+
+
+ protected String getUsersPassword(String username) throws Exception {
+
+ try {
+ final User user = getService().findUser(username);
+ if (user == null) throw new FailedLoginException("User '" + username + "' not found.");
+ if (!user.isActive()) throw new FailedLoginException("User '" + username + "' is disabled.");
+ if (user.getWebDAVPassword() != null && user.getWebDAVPassword().length() > 0)
+ return user.getWebDAVPassword();
+ // If no password has ever been generated, use token instead
+ String tokenEncoded = new String(Base64.encodeBase64(user.getAuthToken()), "US-ASCII");
+ user.setWebDAVPassword(tokenEncoded);
+ new TransactionHelper<Void>().tryExecute(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ getService().updateUser(user);
+ return null;
+ }
+ });
+ return tokenEncoded;
+ } catch (RpcException e) {
+ String error = "An error occurred while communicating with the service";
+ log.error(error, e);
+ throw new Exception(e.getMessage());
+ } catch (UnsupportedEncodingException e) {
+ log.error("", e);
+ throw new Exception(e.getMessage());
+ } catch (Exception e) {
+ log.error("", e);
+ throw new Exception(e.getMessage());
+ }
+ }
+
+
+
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+ <bean id="milton.resource.factory" class="com.ettrema.console.ConsoleResourceFactory">
+ <constructor-arg ref="filesystem.resource.factory" />
+ <constructor-arg value="/console" />
+ <constructor-arg value="/webdav" /> <!-- resource to test authentication against = host root -->
+ <constructor-arg>
+ <list>
+ <bean class="com.ettrema.console.LsFactory" />
+ <bean class="com.ettrema.console.CdFactory" />
+ <bean class="com.ettrema.console.RmFactory" />
+ <bean class="com.ettrema.console.HelpFactory" />
+ <bean class="com.ettrema.console.CpFactory" />
+ <bean class="com.ettrema.console.MkFactory" />
+ <bean class="com.ettrema.console.MkdirFactory" />
+ </list>
+ </constructor-arg>
+ <constructor-arg value="webdav"/> <!-- the web context path -->
+ </bean>
+
+ <bean id="filesystem.resource.factory" class="gr.ebs.gss.server.webdav.milton.GSSResourceFactory">
+ <property name="securityManager" ref="milton.fs.security.manager" />
+ <property name="lockManager" ref="milton.fs.lock.manager" />
+
+ <property name="maxAgeSeconds" value="3600" />
+ <property name="contextPath" value="webdav"/>
+ <!-- the default root is System property user.home -->
+ <!-- enable the property below to set the root elsewhere -->
+ <!--
+ <property name="root" value="/www/webs" />
+ -->
+ </bean>
+
+<!--
+ <bean id="milton.fs.security.manager" class="com.ettrema.http.fs.NullSecurityManager" >
+ <property name="realm" value="aRealm" />
+ </bean>
+ com.ettrema.http.fs.SimpleSecurityManager
+-->
+
+ <bean id="milton.fs.security.manager" class="gr.ebs.gss.server.webdav.milton.GssSecurityManager" >
+ <property name="realm" value="aRealm" />
+
+ </bean>
+
+ <bean id="milton.fs.lock.manager" class="gr.ebs.gss.server.webdav.milton.GssMemoryLockManager" />
+
+ <bean id="auth.service" class="com.bradmcevoy.http.AuthenticationService">
+ <property name="disableDigest" value="false"/>
+ <property name="disableBasic" value="true"/>
+ </bean>
+<!--
+ <bean id="milton.response.handler" class="com.bradmcevoy.http.MsOfficeResponseHandler"/>
+-->
+
+ <bean id="milton.response.handler" class="com.bradmcevoy.http.webdav.DefaultWebDavResponseHandler">
+ <constructor-arg ref="auth.service"/>
+ </bean>
+
+ <!-- The compressing response handler wraps the default response handler and compresses
+ response content. This will only actually perform compression for specific mime types
+ (currently hard coded to text, css and js files) and if the client supports gzip -->
+ <bean id="milton.response.handler.compressing" class="com.bradmcevoy.http.CompressingResponseHandler">
+ <constructor-arg ref="milton.response.handler" />
+ </bean>
+
+
+ <bean id="milton.http.manager" class="com.bradmcevoy.http.HttpManager">
+ <constructor-arg ref="milton.resource.factory" />
+ <constructor-arg ref="milton.response.handler.compressing" />
+ <constructor-arg ref="auth.service" />
+
+ <property name="filters">
+ <list>
+ <!-- This filter will save one file per request. Having
+ it enabled by default causes problems when taking
+ milton-fileserver-test for a spin as the system runs
+ slower and slower until it fails.
+
+ Another manifistation of problems with this filter is
+ that Office 2010 will not put up the authentication
+ requester, nor list the files in a folder.
+
+ <ref bean="milton.debug.filter" />
+ -->
+ </list>
+ </property>
+
+ </bean>
+
+ <!-- If added to the http manager, this filter will output request and responses
+ to the logger -->
+ <bean id="milton.debug.filter" class="com.bradmcevoy.http.DebugFilter" >
+ <!-- By default the debugfilter will log to the current user's home directory -->
+ <!-- To change this behaviour uncomment the following line and set the path you want to log to-->
+ <!--
+ <constructor-arg value="/test"/>
+ -->
+ </bean>
+
+
+</beans>
\ No newline at end of file
--- /dev/null
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=INFO, A1
+
+# A1 is set to be a ConsoleAppender.
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-5p %c %x - %m%n
+
+log4j.appender.A2=org.apache.log4j.FileAppender
+log4j.appender.A2.File=/a.log
+log4j.appender.A2.layout=org.apache.log4j.PatternLayout
+log4j.appender.A2.layout.ConversionPattern=%-5p %c %x - %m%n
+
+log4j.logger.org.springframework=WARN
+log4j.logger.com.bradmcevoy=WARN
+log4j.logger.com.ettrema=WARN
+log4j.logger.com.bradmcevoy.property.BeanPropertySource=WARN
+log4j.logger.com.bradmcevoy.http.webdav.PropFindPropertyBuilder=WARN
+log4j.logger.com.bradmcevoy.http.StaticResourceFilter=WARN
+log4j.logger.com.ettrema.http.fs.SimpleSecurityManager=WARN
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+ <import resource="classpath:applicationContext.xml" />
+
+
+ <bean name="/miltonController" class="com.bradmcevoy.http.MiltonController">
+ <constructor-arg ref="milton.http.manager" />
+ </bean>
+
+ <bean name="/*" class="com.bradmcevoy.http.MiltonController">
+ <constructor-arg ref="milton.http.manager" />
+ </bean>
+
+ <bean name="*" class="com.bradmcevoy.http.MiltonController">
+ <constructor-arg ref="milton.http.manager" />
+ </bean>
+
+ <bean id="urlMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
+ </bean>
+<!--
+ <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
+ <property name="alwaysUseFullPath" value="true"/>
+ <property name="mappings">
+ <props>
+ <prop key="/*">miltonController</prop>
+ </props>
+ </property>
+ </bean>
+-->
+</beans>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
-<web-app>
- <servlet>
- <servlet-name>Webdav</servlet-name>
- <servlet-class>gr.ebs.gss.server.webdav.Webdav</servlet-class>
- <init-param>
- <param-name>input</param-name>
- <param-value>4096</param-value>
- </init-param>
- <init-param>
- <param-name>output</param-name>
- <param-value>4096</param-value>
- </init-param>
- </servlet>
- <servlet-mapping>
- <servlet-name>Webdav</servlet-name>
- <url-pattern>/*</url-pattern>
- </servlet-mapping>
-
- <security-constraint>
- <!-- Protect /, but leave OPTIONS unauthenticated to get around Windows client bug with DIGEST authentication -->
- <web-resource-collection>
- <web-resource-name>GSS</web-resource-name>
- <description>GSS WebDAV</description>
- <url-pattern>/</url-pattern>
- <http-method>HEAD</http-method>
- <http-method>GET</http-method>
- <http-method>POST</http-method>
- <http-method>PUT</http-method>
- <http-method>DELETE</http-method>
- <http-method>PROPFIND</http-method>
- <http-method>PROPPATCH</http-method>
- <http-method>MKCOL</http-method>
- <http-method>COPY</http-method>
- <http-method>MOVE</http-method>
- <http-method>LOCK</http-method>
- <http-method>UNLOCK</http-method>
- </web-resource-collection>
- <auth-constraint>
- <role-name>simpleUser</role-name>
- </auth-constraint>
- <user-data-constraint>
- <description>no description</description>
- <transport-guarantee>NONE</transport-guarantee>
- </user-data-constraint>
- </security-constraint>
-
- <security-constraint>
- <!-- Protect everything for every other path -->
- <web-resource-collection>
- <web-resource-name>GSS</web-resource-name>
- <description>GSS WebDAV</description>
- <url-pattern>/*</url-pattern>
- </web-resource-collection>
- <auth-constraint>
- <role-name>simpleUser</role-name>
- </auth-constraint>
- <user-data-constraint>
- <description>no description</description>
- <transport-guarantee>NONE</transport-guarantee>
- </user-data-constraint>
- </security-constraint>
-
- <login-config>
- <auth-method>DIGEST</auth-method>
- <realm-name>Pithos WebDAV</realm-name>
- </login-config>
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+ version="2.4">
+
+ <servlet>
+ <servlet-name>springDispatcher</servlet-name>
+ <servlet-class>com.bradmcevoy.http.DavEnabledDispatcherServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>springDispatcher</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
- <security-role>
- <description>A plain WebDAV user</description>
- <role-name>simpleUser</role-name>
- </security-role>
-
-</web-app>
\ No newline at end of file
+ <servlet-mapping>
+ <servlet-name>springDispatcher</servlet-name>
+ <url-pattern>/miltonController</url-pattern>
+ </servlet-mapping>
+</web-app>