Package org.uberfire.java.nio.fs.jgit

Source Code of org.uberfire.java.nio.fs.jgit.JGitFileSystem

/*
* Copyright 2012 JBoss Inc
*
* 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.uberfire.java.nio.fs.jgit;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListBranchCommand;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.uberfire.java.nio.IOException;
import org.uberfire.java.nio.base.FileSystemId;
import org.uberfire.java.nio.base.FileSystemState;
import org.uberfire.java.nio.base.options.CommentedOption;
import org.uberfire.java.nio.file.ClosedWatchServiceException;
import org.uberfire.java.nio.file.FileStore;
import org.uberfire.java.nio.file.FileSystem;
import org.uberfire.java.nio.file.InterruptedException;
import org.uberfire.java.nio.file.InvalidPathException;
import org.uberfire.java.nio.file.Path;
import org.uberfire.java.nio.file.PathMatcher;
import org.uberfire.java.nio.file.PatternSyntaxException;
import org.uberfire.java.nio.file.WatchEvent;
import org.uberfire.java.nio.file.WatchKey;
import org.uberfire.java.nio.file.WatchService;
import org.uberfire.java.nio.file.Watchable;
import org.uberfire.java.nio.file.attribute.UserPrincipalLookupService;
import org.uberfire.java.nio.file.spi.FileSystemProvider;

import static org.eclipse.jgit.lib.Repository.*;
import static org.uberfire.commons.validation.Preconditions.*;
import static org.uberfire.java.nio.fs.jgit.util.JGitUtil.*;

public class JGitFileSystem implements FileSystem,
                                       FileSystemId {

    private static final Logger LOGGER = LoggerFactory.getLogger( JGitFileSystem.class );

    private static final Set<String> SUPPORTED_ATTR_VIEWS = Collections.unmodifiableSet( new HashSet<String>() {{
        add( "basic" );
        add( "version" );
    }} );

    private final JGitFileSystemProvider provider;
    private final Git gitRepo;
    private final ListBranchCommand.ListMode listMode;
    private final String toStringContent;
    private boolean isClose = false;
    private final FileStore fileStore;
    private final String name;
    private final CredentialsProvider credential;
    private final Map<WatchService, Queue<WatchKey>> events = new ConcurrentHashMap<WatchService, Queue<WatchKey>>();
    private final Collection<WatchService> watchServices = new ArrayList<WatchService>();
    private FileSystemState state = FileSystemState.NORMAL;
    private CommitInfo batchCommitInfo = null;
    private boolean hadCommitOnBatchState = false;

    JGitFileSystem( final JGitFileSystemProvider provider,
                    final Map<String, String> fullHostNames,
                    final Git git,
                    final String name,
                    final CredentialsProvider credential ) {
        this( provider, fullHostNames, git, name, null, credential );
    }

    JGitFileSystem( final JGitFileSystemProvider provider,
                    final Map<String, String> fullHostNames,
                    final Git git,
                    final String name,
                    final ListBranchCommand.ListMode listMode,
                    final CredentialsProvider credential ) {
        this.provider = checkNotNull( "provider", provider );
        this.gitRepo = checkNotNull( "git", git );
        this.name = checkNotEmpty( "name", name );
        this.credential = checkNotNull( "credential", credential );
        this.listMode = listMode;
        this.fileStore = new JGitFileStore( gitRepo.getRepository() );
        if ( fullHostNames != null && !fullHostNames.isEmpty() ) {
            final StringBuilder sb = new StringBuilder();
            final Iterator<Map.Entry<String, String>> iterator = fullHostNames.entrySet().iterator();
            while ( iterator.hasNext() ) {
                final Map.Entry<String, String> entry = iterator.next();
                sb.append( entry.getKey() ).append( "://" ).append( entry.getValue() ).append( "/" ).append( name );
                if ( iterator.hasNext() ) {
                    sb.append( "\n" );
                }
            }
            toStringContent = sb.toString();
        } else {
            toStringContent = "git://" + name;
        }
    }

    @Override
    public String id() {
        return name;
    }

    public String getName() {
        return name;
    }

    public Git gitRepo() {
        return gitRepo;
    }

    public CredentialsProvider getCredential() {
        return credential;
    }

    @Override
    public FileSystemProvider provider() {
        return provider;
    }

    @Override
    public boolean isOpen() {
        return !isClose;
    }

    @Override
    public boolean isReadOnly() {
        return false;
    }

    @Override
    public String getSeparator() {
        return "/";
    }

    @Override
    public Iterable<Path> getRootDirectories() {
        checkClose();
        return new Iterable<Path>() {
            @Override
            public Iterator<Path> iterator() {
                return new Iterator<Path>() {

                    Iterator<Ref> branches = null;

                    @Override
                    public boolean hasNext() {
                        if ( branches == null ) {
                            init();
                        }
                        return branches.hasNext();
                    }

                    private void init() {
                        branches = branchList( gitRepo, listMode ).iterator();
                    }

                    @Override
                    public Path next() {
                        if ( branches == null ) {
                            init();
                        }
                        return JGitPathImpl.createRoot( JGitFileSystem.this, "/", shortenRefName( branches.next().getName() ) + "@" + name, false );
                    }

                    @Override
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }

    @Override
    public Iterable<FileStore> getFileStores() {
        checkClose();
        return new Iterable<FileStore>() {
            @Override
            public Iterator<FileStore> iterator() {
                return new Iterator<FileStore>() {

                    private int i = 0;

                    @Override
                    public boolean hasNext() {
                        return i < 1;
                    }

                    @Override
                    public FileStore next() {
                        if ( i < 1 ) {
                            i++;
                            return fileStore;
                        } else {
                            throw new NoSuchElementException();
                        }
                    }

                    @Override
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }

    @Override
    public Set<String> supportedFileAttributeViews() {
        checkClose();
        return SUPPORTED_ATTR_VIEWS;
    }

    @Override
    public Path getPath( final String first,
                         final String... more )
            throws InvalidPathException {
        checkClose();
        if ( first == null || first.trim().isEmpty() ) {
            return new JGitFSPath( this );
        }

        if ( more == null || more.length == 0 ) {
            return JGitPathImpl.create( this, first, JGitPathImpl.DEFAULT_REF_TREE + "@" + name, false );
        }

        final StringBuilder sb = new StringBuilder();
        for ( final String segment : more ) {
            if ( segment.length() > 0 ) {
                if ( sb.length() > 0 ) {
                    sb.append( getSeparator() );
                }
                sb.append( segment );
            }
        }
        return JGitPathImpl.create( this, sb.toString(), first + "@" + name, false );
    }

    @Override
    public PathMatcher getPathMatcher( final String syntaxAndPattern )
            throws IllegalArgumentException, PatternSyntaxException, UnsupportedOperationException {
        checkClose();
        checkNotEmpty( "syntaxAndPattern", syntaxAndPattern );
        throw new UnsupportedOperationException();
    }

    @Override
    public UserPrincipalLookupService getUserPrincipalLookupService()
            throws UnsupportedOperationException {
        checkClose();
        throw new UnsupportedOperationException();
    }

    @Override
    public WatchService newWatchService()
            throws UnsupportedOperationException, IOException {
        checkClose();
        final WatchService ws = new WatchService() {
            private boolean wsClose = false;

            @Override
            public WatchKey poll() throws ClosedWatchServiceException {
                return events.get( this ).poll();
            }

            @Override
            public WatchKey poll( long timeout,
                                  TimeUnit unit ) throws ClosedWatchServiceException, org.uberfire.java.nio.file.InterruptedException {
                return events.get( this ).poll();
            }

            @Override
            public synchronized WatchKey take() throws ClosedWatchServiceException, InterruptedException {
                while ( true ) {
                    if ( wsClose || isClose ) {
                        throw new ClosedWatchServiceException();
                    } else if ( events.get( this ).size() > 0 ) {
                        return events.get( this ).poll();
                    } else {
                        try {
                            this.wait();
                        } catch ( final java.lang.InterruptedException e ) {
                        }
                    }
                }
            }

            @Override
            public boolean isClose() {
                return isClose;
            }

            @Override
            public synchronized void close() throws IOException {
                wsClose = true;
                notifyAll();
                watchServices.remove( this );
            }

            @Override
            public String toString() {
                return "WatchService{" +
                        "FileSystem=" + JGitFileSystem.this.toString() +
                        '}';
            }
        };
        events.put( ws, new ConcurrentLinkedQueue<WatchKey>() );
        watchServices.add( ws );
        return ws;
    }

    @Override
    public void close() throws IOException {
        if ( isClose ) {
            return;
        }
        gitRepo.getRepository().close();
        isClose = true;
        try {

            for ( final WatchService ws : new ArrayList<WatchService>( watchServices ) ) {
                try {
                    ws.close();
                } catch ( final Exception ex ) {
                    LOGGER.error( "Can't close watch service [" + toString() + "]", ex );
                }
            }
            watchServices.clear();
            events.clear();
        } catch ( final Exception ex ) {
            LOGGER.error( "Error during close of WatchServices [" + toString() + "]", ex );
        } finally {
            provider.onCloseFileSystem( this );
        }
    }

    private void checkClose() throws IllegalStateException {
        if ( isClose ) {
            throw new IllegalStateException( "FileSystem is close." );
        }
    }

    @Override
    public boolean equals( Object o ) {
        if ( this == o ) {
            return true;
        }
        if ( o == null || getClass() != o.getClass() ) {
            return false;
        }

        JGitFileSystem that = (JGitFileSystem) o;

        if ( fileStore != null ? !fileStore.equals( that.fileStore ) : that.fileStore != null ) {
            return false;
        }
        if ( !gitRepo.equals( that.gitRepo ) ) {
            return false;
        }
        if ( listMode != that.listMode ) {
            return false;
        }
        if ( !name.equals( that.name ) ) {
            return false;
        }
        if ( !provider.equals( that.provider ) ) {
            return false;
        }

        return true;
    }

    @Override
    public String toString() {
        return toStringContent;
    }

    @Override
    public int hashCode() {
        int result = provider.hashCode();
        result = 31 * result + gitRepo.hashCode();
        result = 31 * result + ( listMode != null ? listMode.hashCode() : 0 );
        result = 31 * result + ( fileStore != null ? fileStore.hashCode() : 0 );
        result = 31 * result + name.hashCode();
        return result;
    }

    public void publishEvents( final Path watchable,
                               final List<WatchEvent<?>> elist ) {
        if ( this.events.isEmpty() ) {
            return;
        }

        final WatchKey wk = new WatchKey() {

            @Override
            public boolean isValid() {
                return true;
            }

            @Override
            public List<WatchEvent<?>> pollEvents() {
                return new ArrayList<WatchEvent<?>>( elist );
            }

            @Override
            public boolean reset() {
                return isOpen();
            }

            @Override
            public void cancel() {
            }

            @Override
            public Watchable watchable() {
                return watchable;
            }
        };

        for ( final Map.Entry<WatchService, Queue<WatchKey>> watchServiceQueueEntry : events.entrySet() ) {
            watchServiceQueueEntry.getValue().add( wk );
            final WatchService ws = watchServiceQueueEntry.getKey();
            synchronized ( ws ) {
                ws.notifyAll();
            }
        }
    }

    @Override
    public void dispose() {
        provider.onDisposeFileSystem( this );
    }

    public boolean isOnBatch() {
        return state.equals( FileSystemState.BATCH );
    }

    public void setState( String state ) {
        try {
            this.state = FileSystemState.valueOf( state );
        } catch ( final Exception ex ) {
            this.state = FileSystemState.NORMAL;
        }
    }

    private CommitInfo buildCommitInfo( final String defaultMessage,
                                        final CommentedOption op ) {
        String sessionId = null;
        String name = null;
        String email = null;
        String message = defaultMessage;
        TimeZone timeZone = null;
        Date when = null;

        if ( op != null ) {
            sessionId = op.getSessionId();
            name = op.getName();
            email = op.getEmail();
            if ( op.getMessage() != null && !op.getMessage().trim().isEmpty() ) {
                message = op.getMessage();
            }
            timeZone = op.getTimeZone();
            when = op.getWhen();
        }

        return new CommitInfo( sessionId, name, email, message, timeZone, when );
    }

    public void setBatchCommitInfo( final String defaultMessage,
                                    final CommentedOption op ) {
        this.batchCommitInfo = buildCommitInfo( defaultMessage, op );
    }

    public void setHadCommitOnBatchState( boolean hadCommitOnBatchState ) {
        this.hadCommitOnBatchState = hadCommitOnBatchState;
    }

    public boolean isHadCommitOnBatchState() {
        return hadCommitOnBatchState;
    }

    public void setBatchCommitInfo( CommitInfo batchCommitInfo ) {
        this.batchCommitInfo = batchCommitInfo;
    }

    public CommitInfo getBatchCommitInfo() {
        return batchCommitInfo;
    }
}
TOP

Related Classes of org.uberfire.java.nio.fs.jgit.JGitFileSystem

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.