merge with branch 1.x

This commit is contained in:
Sebastian Sdorra
2014-12-06 15:42:10 +01:00
75 changed files with 5923 additions and 516 deletions

View File

@@ -35,23 +35,28 @@ package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Throwables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.ImportResult.Builder;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Abstract base class for directory based {@link ImportHandler} and
* {@link AdvancedImportHandler}.
*
* @author Sebastian Sdorra
* @since 1.12
*/
public abstract class AbstactImportHandler implements ImportHandler
public abstract class AbstactImportHandler implements AdvancedImportHandler
{
/**
@@ -63,80 +68,65 @@ public abstract class AbstactImportHandler implements ImportHandler
//~--- get methods ----------------------------------------------------------
/**
* Method description
* Returns array of repository directory names.
*
*
* @return
* @return repository directory names
*/
protected abstract String[] getDirectoryNames();
/**
* Method description
* Returns repository handler.
*
*
* @return
* @return repository handler
*/
protected abstract AbstractRepositoryHandler<?> getRepositoryHandler();
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param manager
*
*
* @return
* @throws IOException
* @throws RepositoryException
* {@inheritDoc}
*/
@Override
public List<String> importRepositories(RepositoryManager manager)
throws IOException, RepositoryException
{
List<String> imported = new ArrayList<String>();
if (logger.isTraceEnabled())
{
logger.trace("search for repositories to import");
}
List<String> repositoryNames =
RepositoryUtil.getRepositoryNames(getRepositoryHandler(),
getDirectoryNames());
for (String repositoryName : repositoryNames)
{
if (logger.isTraceEnabled())
{
logger.trace("check repository {} for import", repositoryName);
}
Repository repository = manager.get(getTypeName(), repositoryName);
if (repository == null)
{
importRepository(manager, repositoryName);
imported.add(repositoryName);
}
else if (logger.isDebugEnabled())
{
logger.debug("repository {} is allready managed", repositoryName);
}
}
return imported;
return doRepositoryImport(manager, true).getImportedDirectories();
}
/**
* Method description
* {@inheritDoc}
*/
@Override
public ImportResult importRepositoriesFromDirectory(RepositoryManager manager)
{
try
{
return doRepositoryImport(manager, false);
}
catch (IOException ex)
{
// should never happen
throw Throwables.propagate(ex);
}
catch (RepositoryException ex)
{
// should never happen
throw Throwables.propagate(ex);
}
}
/**
* Creates a repository.
*
*
* @param repositoryDirectory
* @param repositoryName
* @param repositoryDirectory repository base directory
* @param repositoryName name of the repository
*
* @return
* @return repository
*
* @throws IOException
* @throws RepositoryException
@@ -154,6 +144,118 @@ public abstract class AbstactImportHandler implements ImportHandler
return repository;
}
/**
* Repository import.
*
*
* @param manager repository manager
* @param throwExceptions true to throw exception
*
* @return import result
*
* @throws IOException
* @throws RepositoryException
*/
private ImportResult doRepositoryImport(RepositoryManager manager,
boolean throwExceptions)
throws IOException, RepositoryException
{
Builder builder = ImportResult.builder();
logger.trace("search for repositories to import");
try
{
List<String> repositoryNames =
RepositoryUtil.getRepositoryNames(getRepositoryHandler(),
getDirectoryNames());
for (String repositoryName : repositoryNames)
{
importRepository(manager, builder, throwExceptions, repositoryName);
}
}
catch (IOException ex)
{
handleException(ex, throwExceptions);
}
return builder.build();
}
/**
* Method description
*
*
* @param ex
* @param throwExceptions
* @param <T>
*
* @throws T
*/
private <T extends Exception> void handleException(T ex,
boolean throwExceptions)
throws T
{
logger.warn("error durring repository directory import", ex);
if (throwExceptions)
{
throw ex;
}
}
/**
* Method description
*
*
* @param manager
* @param builder
* @param throwExceptions
* @param repositoryName
*
* @throws IOException
* @throws RepositoryException
*/
private void importRepository(RepositoryManager manager, Builder builder,
boolean throwExceptions, String repositoryName)
throws IOException, RepositoryException
{
logger.trace("check repository {} for import", repositoryName);
Repository repository = manager.get(getTypeName(), repositoryName);
if (repository == null)
{
try
{
importRepository(manager, repositoryName);
builder.addImportedDirectory(repositoryName);
}
catch (IOException ex)
{
builder.addFailedDirectory(repositoryName);
handleException(ex, throwExceptions);
}
catch (IllegalStateException ex)
{
builder.addFailedDirectory(repositoryName);
handleException(ex, throwExceptions);
}
catch (RepositoryException ex)
{
builder.addFailedDirectory(repositoryName);
handleException(ex, throwExceptions);
}
}
else if (logger.isDebugEnabled())
{
logger.debug("repository {} is allready managed", repositoryName);
}
}
/**
* Method description
*

View File

@@ -0,0 +1,58 @@
/**
* Copyright (c) 2014, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository;
/**
* Searches and import existing repositories. The {@link AdvancedImportHandler}
* gives more control over the result of the import as the
* {@link ImportHandler}.
*
* @author Sebastian Sdorra
* @since 1.43
*/
public interface AdvancedImportHandler extends ImportHandler
{
/**
* Import existing and non managed repositories. Returns result which
* contains names of the successfully imported directories and the names of
* the failed directories
*
*
* @param manager The global {@link RepositoryManager}
*
* @return result which contains names of the successfully imported
* directories and the names of the failed directories.
*/
public ImportResult importRepositoriesFromDirectory(
RepositoryManager manager);
}

View File

@@ -0,0 +1,239 @@
/**
* Copyright (c) 2014, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import static com.google.common.base.Preconditions.*;
//~--- JDK imports ------------------------------------------------------------
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Import result of the {@link AdvancedImportHandler}.
*
* @author Sebastian Sdorra
* @since 1.43
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "import-result")
public final class ImportResult
{
/**
* Constructs ...
*
*/
ImportResult() {}
/**
* Constructs a new import result.
*
*
* @param importedDirectories imported directories
* @param failedDirectories failed directories
*/
public ImportResult(List<String> importedDirectories,
List<String> failedDirectories)
{
this.importedDirectories = checkNotNull(importedDirectories,
"list of imported directories is required");
this.failedDirectories = checkNotNull(failedDirectories,
"list of failed directories is required");
}
//~--- methods --------------------------------------------------------------
/**
* Returns a import result builder.
*
*
* @return import result builder
*/
public static Builder builder()
{
return new Builder();
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final ImportResult other = (ImportResult) obj;
return Objects.equal(importedDirectories, other.importedDirectories)
&& Objects.equal(failedDirectories, other.failedDirectories);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode()
{
return Objects.hashCode(importedDirectories, failedDirectories);
}
/**
* {@inheritDoc}
*/
@Override
public String toString()
{
//J-
return Objects.toStringHelper(this)
.add("importedDirectories", importedDirectories)
.add("failedDirectories", failedDirectories)
.toString();
//J+
}
//~--- get methods ----------------------------------------------------------
/**
* Returns list of failed directories.
*
*
* @return list of failed directories
*/
public List<String> getFailedDirectories()
{
return failedDirectories;
}
/**
* Returns list of successfully imported directories.
*
*
* @return list of successfully imported directories
*/
public List<String> getImportedDirectories()
{
return importedDirectories;
}
//~--- inner classes --------------------------------------------------------
/**
* Builder for {@link ImportResult}.
*/
public static class Builder
{
/**
* Constructs ...
*
*/
private Builder() {}
//~--- methods ------------------------------------------------------------
/**
* Adds a failed directory to the import result.
*
*
* @param name name of the directory
*
* @return {@code this}
*/
public Builder addFailedDirectory(String name)
{
this.failedDirectories.add(name);
return this;
}
/**
* Adds a successfully imported directory to the import result.
*
*
* @param name name of the directory
*
* @return {@code this}
*/
public Builder addImportedDirectory(String name)
{
this.importedDirectories.add(name);
return this;
}
/**
* Builds the final import result.
*
*
* @return final import result
*/
public ImportResult build()
{
return new ImportResult(ImmutableList.copyOf(importedDirectories),
ImmutableList.copyOf(failedDirectories));
}
//~--- fields -------------------------------------------------------------
/** successfully imported directories */
private final List<String> importedDirectories = Lists.newArrayList();
/** failed directories */
private final List<String> failedDirectories = Lists.newArrayList();
}
//~--- fields ---------------------------------------------------------------
/** failed directories */
private List<String> failedDirectories;
/** successfully imported directories */
private List<String> importedDirectories;
}

View File

@@ -0,0 +1,121 @@
/**
* Copyright (c) 2014, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.api;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Objects;
/**
* Abstract class for bundle or unbundle command.
*
* @author Sebastian Sdorra
* @since 1.43
*/
public abstract class AbstractBundleOrUnbundleCommandResponse
{
/**
* Constructs a new bundle/unbundle response.
*
*
* @param changesetCount count of bundled/unbundled changesets
*/
protected AbstractBundleOrUnbundleCommandResponse(long changesetCount)
{
this.changesetCount = changesetCount;
}
//~--- methods --------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final AbstractBundleOrUnbundleCommandResponse other =
(AbstractBundleOrUnbundleCommandResponse) obj;
return Objects.equal(changesetCount, other.changesetCount);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode()
{
return Objects.hashCode(changesetCount);
}
/**
* {@inheritDoc}
*/
@Override
public String toString()
{
//J-
return Objects.toStringHelper(this)
.add("changesetCount", changesetCount)
.toString();
//J+
}
//~--- get methods ----------------------------------------------------------
/**
* Returns the count of bundled/unbundled changesets.
*
*
* @return count of bundled/unbundled changesets
*/
public long getChangesetCount()
{
return changesetCount;
}
//~--- fields ---------------------------------------------------------------
/** count of bundled/unbundled changesets */
private final long changesetCount;
}

View File

@@ -0,0 +1,185 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.api;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.io.ByteSink;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import com.google.common.io.OutputSupplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.spi.BundleCommand;
import sonia.scm.repository.spi.BundleCommandRequest;
import static com.google.common.base.Preconditions.*;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
/**
* The bundle command dumps a repository to a byte source such as a file. The
* created bundle can be restored to an empty repository with the
* {@link UnbundleCommandBuilder}.
*
* @author Sebastian Sdorra <s.sdorra@gmail.com>
* @since 1.43
*/
public final class BundleCommandBuilder
{
/** logger for BundleCommandBuilder */
private static final Logger logger =
LoggerFactory.getLogger(BundleCommandBuilder.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs a new {@link BundleCommandBuilder}.
*
*
* @param bundleCommand bundle command implementation
* @param repository repository
*/
BundleCommandBuilder(BundleCommand bundleCommand, Repository repository)
{
this.bundleCommand = bundleCommand;
this.repository = repository;
}
//~--- methods --------------------------------------------------------------
/**
* Dumps the repository to the given {@link File}.
*
* @param outputFile output file
*
* @return bundle response
*
* @throws IOException
* @throws RepositoryException
*/
public BundleResponse bundle(File outputFile)
throws IOException, RepositoryException
{
checkArgument((outputFile != null) &&!outputFile.exists(),
"file is null or exists already");
BundleCommandRequest request =
new BundleCommandRequest(Files.asByteSink(outputFile));
logger.info("create bundle at {} for repository {}", outputFile,
repository.getId());
return bundleCommand.bundle(request);
}
/**
* Dumps the repository to the given {@link OutputStream}.
*
*
* @param outputStream output stream
*
* @return bundle response
*
* @throws IOException
* @throws RepositoryException
*/
public BundleResponse bundle(OutputStream outputStream)
throws IOException, RepositoryException
{
checkNotNull(outputStream, "output stream is required");
logger.info("bundle {} to output stream", repository.getId());
return bundleCommand.bundle(
new BundleCommandRequest(asByteSink(outputStream)));
}
/**
* Dumps the repository to the given {@link ByteSink}.
*
* @param sink byte sink
*
* @return bundle response
*
* @throws IOException
* @throws RepositoryException
*/
public BundleResponse bundle(ByteSink sink)
throws IOException, RepositoryException
{
checkNotNull(sink, "byte sink is required");
logger.info("bundle {} to byte sink");
return bundleCommand.bundle(new BundleCommandRequest(sink));
}
/**
* Converts an {@link OutputStream} into a {@link ByteSink}.
*
*
* @param outputStream ouput stream to convert
*
* @return converted byte sink
*/
private ByteSink asByteSink(final OutputStream outputStream)
{
return ByteStreams.asByteSink(new OutputSupplier<OutputStream>()
{
@Override
public OutputStream getOutput() throws IOException
{
return outputStream;
}
});
}
//~--- fields ---------------------------------------------------------------
/** bundle command implementation */
private final BundleCommand bundleCommand;
/** repository */
private final Repository repository;
}

View File

@@ -0,0 +1,56 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.api;
/**
* Response of bundle command.
*
* @author Sebastian Sdorra <s.sdorra@gmail.com>
* @since 1.43
*/
public final class BundleResponse
extends AbstractBundleOrUnbundleCommandResponse
{
/**
* Constructs a new bundle response.
*
*
* @param changesetCount count of bundled changesets
*/
public BundleResponse(long changesetCount)
{
super(changesetCount);
}
}

View File

@@ -56,5 +56,10 @@ public enum Command
/**
* @since 1.31
*/
INCOMING, OUTGOING, PUSH, PULL;
INCOMING, OUTGOING, PUSH, PULL,
/**
* @since 1.43
*/
BUNDLE, UNBUNDLE;
}

View File

@@ -50,6 +50,7 @@ import sonia.scm.security.RepositoryPermission;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.net.URL;
/**
* The pull command pull changes from a other repository.
@@ -83,6 +84,38 @@ public final class PullCommandBuilder
//~--- methods --------------------------------------------------------------
/**
* Pull all changes from the given remote url.
*
*
* @param url remote url
*
* @return informations over the executed pull command
*
* @throws IOException
* @throws RepositoryException
*
* @since 1.43
*/
public PullResponse pull(String url)
throws IOException, RepositoryException
{
Subject subject = SecurityUtils.getSubject();
//J-
subject.checkPermission(
new RepositoryPermission(localRepository, PermissionType.WRITE)
);
//J+
URL remoteUrl = new URL(url);
request.reset();
request.setRemoteUrl(remoteUrl);
logger.info("pull changes from url {}", url);
return command.pull(request);
}
/**
* Pull all changes from the given remote repository.
*
@@ -108,6 +141,7 @@ public final class PullCommandBuilder
);
//J+
request.reset();
request.setRemoteRepository(remoteRepository);
logger.info("pull changes from {}", remoteRepository);

View File

@@ -30,6 +30,7 @@
*/
package sonia.scm.repository.api;
//~--- non-JDK imports --------------------------------------------------------
@@ -37,6 +38,9 @@ package sonia.scm.repository.api;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryException;
@@ -48,15 +52,25 @@ import sonia.scm.security.RepositoryPermission;
import java.io.IOException;
import java.net.URL;
/**
* The push command push changes to a other repository.
*
*
* @author Sebastian Sdorra
* @since 1.31
*/
public final class PushCommandBuilder
{
/**
* the logger for PushCommandBuilder
*/
private static final Logger logger =
LoggerFactory.getLogger(PushCommandBuilder.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs a new PushCommandBuilder.
*
@@ -90,11 +104,39 @@ public final class PushCommandBuilder
);
//J+
logger.info("push changes to repository {}", remoteRepository.getId());
request.reset();
request.setRemoteRepository(remoteRepository);
return command.push(request);
}
/**
* Push all changes to the given remote url.
*
* @param url url of a remote repository
*
* @return informations of the executed push command
*
* @throws IOException
* @throws RepositoryException
*
* @since 1.43
*/
public PushResponse push(String url) throws IOException, RepositoryException
{
URL remoteUrl = new URL(url);
logger.info("push changes to url {}", url);
request.reset();
request.setRemoteUrl(remoteUrl);
return command.push(request);
}
//~--- fields ---------------------------------------------------------------
/** push command implementation */

View File

@@ -83,6 +83,8 @@ import java.io.IOException;
* @apiviz.uses sonia.scm.repository.api.OutgoingCommandBuilder
* @apiviz.uses sonia.scm.repository.api.PullCommandBuilder
* @apiviz.uses sonia.scm.repository.api.PushCommandBuilder
* @apiviz.uses sonia.scm.repository.api.BundleCommandBuilder
* @apiviz.uses sonia.scm.repository.api.UnbundleCommandBuilder
*/
public final class RepositoryService implements Closeable
{
@@ -204,6 +206,25 @@ public final class RepositoryService implements Closeable
repository, preProcessorUtil);
}
/**
* The bundle command creates an archive from the repository.
*
* @return instance of {@link BundleCommandBuilder}
* @throws CommandNotSupportedException if the command is not supported
* by the implementation of the repository service provider.
* @since 1.43
*/
public BundleCommandBuilder getBundleCommand()
{
if (logger.isDebugEnabled())
{
logger.debug("create bundle command for repository {}",
repository.getName());
}
return new BundleCommandBuilder(provider.getBundleCommand(), repository);
}
/**
* The cat command show the content of a given file.
*
@@ -370,6 +391,26 @@ public final class RepositoryService implements Closeable
repository);
}
/**
* The unbundle command restores a repository from the given bundle.
*
* @return instance of {@link UnbundleCommandBuilder}
* @throws CommandNotSupportedException if the command is not supported
* by the implementation of the repository service provider.
* @since 1.43
*/
public UnbundleCommandBuilder getUnbundleCommand()
{
if (logger.isDebugEnabled())
{
logger.debug("create bundle command for repository {}",
repository.getName());
}
return new UnbundleCommandBuilder(provider.getUnbundleCommand(),
repository);
}
/**
* Returns true if the command is supported by the repository service.
*
@@ -390,7 +431,7 @@ public final class RepositoryService implements Closeable
* @param feature feature
*
* @return true if the feature is supported
*
*
* @since 1.25
*/
public boolean isSupported(Feature feature)

View File

@@ -0,0 +1,275 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.api;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.io.ByteSource;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import com.google.common.io.InputSupplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.spi.UnbundleCommand;
import sonia.scm.repository.spi.UnbundleCommandRequest;
import static com.google.common.base.Preconditions.*;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
/**
* The unbundle command can restore an empty repository from a bundle. The
* bundle can be created with the {@link BundleCommandBuilder}.
*
* @author Sebastian Sdorra <s.sdorra@gmail.com>
* @since 1.43
*/
public final class UnbundleCommandBuilder
{
/** logger for UnbundleCommandBuilder */
private static final Logger logger =
LoggerFactory.getLogger(UnbundleCommandBuilder.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs a new UnbundleCommandBuilder.
*
*
* @param unbundleCommand unbundle command implementation
* @param repository repository
*/
public UnbundleCommandBuilder(UnbundleCommand unbundleCommand,
Repository repository)
{
this.unbundleCommand = unbundleCommand;
this.repository = repository;
}
//~--- methods --------------------------------------------------------------
/**
* Restores the repository from the given bundle.
*
*
* @param inputFile input file
*
* @return unbundle response
*
* @throws IOException
* @throws RepositoryException
*/
public UnbundleResponse unbundle(File inputFile)
throws IOException, RepositoryException
{
checkArgument((inputFile != null) && inputFile.exists(),
"existing file is required");
UnbundleCommandRequest request =
createRequest(Files.asByteSource(inputFile));
logger.info("unbundle archive {} at {}", inputFile, repository.getId());
return unbundleCommand.unbundle(request);
}
/**
* Restores the repository from the given bundle.
*
*
* @param inputStream input stream
*
* @return unbundle response
*
* @throws IOException
* @throws RepositoryException
*/
public UnbundleResponse unbundle(InputStream inputStream)
throws IOException, RepositoryException
{
checkNotNull(inputStream, "input stream is required");
logger.info("unbundle archive from stream");
return unbundleCommand.unbundle(createRequest(asByteSource(inputStream)));
}
/**
* Restores the repository from the given bundle.
*
*
* @param byteSource byte source
*
* @return unbundle response
*
* @throws IOException
* @throws RepositoryException
*/
public UnbundleResponse unbundle(ByteSource byteSource)
throws IOException, RepositoryException
{
checkNotNull(byteSource, "byte source is required");
logger.info("unbundle from byte source");
return unbundleCommand.unbundle(createRequest(byteSource));
}
//~--- set methods ----------------------------------------------------------
/**
* Set to {@code true} if bundle is gzip compressed. Default is {@code false}.
*
*
* @param compressed {@code true} if bundle is gzip compressed
*
* @return {@code this}
*/
public UnbundleCommandBuilder setCompressed(boolean compressed)
{
this.compressed = compressed;
return this;
}
//~--- methods --------------------------------------------------------------
/**
* Converts an {@link InputStream} into a {@link ByteSource}.
*
*
* @param inputStream input stream
*
* @return byte source
*/
private ByteSource asByteSource(final InputStream inputStream)
{
return ByteStreams.asByteSource(new InputSupplier<InputStream>()
{
@Override
public InputStream getInput() throws IOException
{
return inputStream;
}
});
}
/**
* Creates the {@link UnbundleCommandRequest}.
*
*
* @param source byte source
*
* @return the create request
*/
private UnbundleCommandRequest createRequest(ByteSource source)
{
ByteSource bs;
if (compressed)
{
logger.debug("decode gzip stream for unbundle command");
bs = new CompressedByteSource(source);
}
else
{
bs = source;
}
return new UnbundleCommandRequest(bs);
}
//~--- inner classes --------------------------------------------------------
/**
* ByteSource which is able to handle gzip compressed resources.
*/
private static class CompressedByteSource extends ByteSource
{
/**
* Constructs ...
*
*
* @param wrapped
*/
public CompressedByteSource(ByteSource wrapped)
{
this.wrapped = wrapped;
}
//~--- methods ------------------------------------------------------------
/**
* Opens the stream for reading the compressed source.
*
*
* @return input stream
*
* @throws IOException
*/
@Override
public InputStream openStream() throws IOException
{
return new GZIPInputStream(wrapped.openStream());
}
//~--- fields -------------------------------------------------------------
/** Field description */
private final ByteSource wrapped;
}
//~--- fields ---------------------------------------------------------------
/** repository */
private final Repository repository;
/** unbundle command implementation */
private final UnbundleCommand unbundleCommand;
/** Field description */
private boolean compressed = false;
}

View File

@@ -0,0 +1,55 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.api;
/**
* Response of unbundle command.
*
* @author Sebastian Sdorra <s.sdorra@gmail.com>
* @since 1.43
*/
public class UnbundleResponse extends AbstractBundleOrUnbundleCommandResponse
{
/**
* Constructs a new unbundle response.
*
*
* @param changesetCount count of unbundled changesets
*/
public UnbundleResponse(long changesetCount)
{
super(changesetCount);
}
}

View File

@@ -0,0 +1,67 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.api.BundleResponse;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
/**
* Service provider implementation for the bundle command.
*
* @author Sebastian Sdorra <s.sdorra@gmail.com>
* @since 1.43
*/
public interface BundleCommand
{
/**
* The bundle command dumps a repository to a byte source such as a file.
*
*
* @param request bundle command request
*
* @return bundle response
*
* @throws IOException
* @throws RepositoryException
*/
public BundleResponse bundle(BundleCommandRequest request)
throws IOException, RepositoryException;
}

View File

@@ -0,0 +1,110 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Objects;
import com.google.common.io.ByteSink;
/**
* Request for the bundle command.
*
* @author Sebastian Sdorra <s.sdorra@gmail.com>
* @since 1.43
*/
public final class BundleCommandRequest
{
/**
* Constructs a new bundle command request.
*
*
* @param archive byte sink archive
*/
public BundleCommandRequest(ByteSink archive)
{
this.archive = archive;
}
//~--- methods --------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final BundleCommandRequest other = (BundleCommandRequest) obj;
return Objects.equal(archive, other.archive);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode()
{
return Objects.hashCode(archive);
}
//~--- get methods ----------------------------------------------------------
/**
* Returns the archive as {@link ByteSink}.
*
*
* @return {@link ByteSink} archive.
*/
ByteSink getArchive()
{
return archive;
}
//~--- fields ---------------------------------------------------------------
/** byte sink archive */
private final ByteSink archive;
}

View File

@@ -33,7 +33,8 @@
package sonia.scm.repository.spi;
/**
*
* Request object for {@link PullCommand}.
*
* @author Sebastian Sdorra
* @since 1.31
*/

View File

@@ -33,6 +33,7 @@
package sonia.scm.repository.spi;
/**
* Request object for {@link PushCommand}.
*
* @author Sebastian Sdorra
* @since 1.31

View File

@@ -30,6 +30,7 @@
*/
package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
@@ -38,12 +39,16 @@ import com.google.common.base.Objects;
import sonia.scm.repository.Repository;
//~--- JDK imports ------------------------------------------------------------
import java.net.URL;
/**
*
* @author Sebastian Sdorra
* @since 1.31
*/
public abstract class RemoteCommandRequest
public abstract class RemoteCommandRequest implements Resetable
{
/**
@@ -64,7 +69,8 @@ public abstract class RemoteCommandRequest
final RemoteCommandRequest other = (RemoteCommandRequest) obj;
return Objects.equal(remoteRepository, other.remoteRepository);
return Objects.equal(remoteRepository, other.remoteRepository)
&& Objects.equal(remoteUrl, other.remoteUrl);
}
/**
@@ -73,7 +79,19 @@ public abstract class RemoteCommandRequest
@Override
public int hashCode()
{
return Objects.hashCode(remoteRepository);
return Objects.hashCode(remoteRepository, remoteUrl);
}
/**
* Resets the request object.
*
* @since 1.43
*/
@Override
public void reset()
{
remoteRepository = null;
remoteUrl = null;
}
/**
@@ -82,10 +100,10 @@ public abstract class RemoteCommandRequest
@Override
public String toString()
{
//J-
return Objects.toStringHelper(this)
.add("remoteRepository", remoteRepository)
.add("remoteUrl", remoteUrl)
.toString();
//J+
}
@@ -102,6 +120,19 @@ public abstract class RemoteCommandRequest
this.remoteRepository = remoteRepository;
}
/**
* Method description
*
*
* @param remoteUrl
*
* @since 1.43
*/
public void setRemoteUrl(URL remoteUrl)
{
this.remoteUrl = remoteUrl;
}
//~--- get methods ----------------------------------------------------------
/**
@@ -115,8 +146,24 @@ public abstract class RemoteCommandRequest
return remoteRepository;
}
/**
* Method description
*
*
* @return
*
* @since 1.43
*/
URL getRemoteUrl()
{
return remoteUrl;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
protected Repository remoteRepository;
/** remote url */
protected URL remoteUrl;
}

View File

@@ -115,6 +115,19 @@ public abstract class RepositoryServiceProvider implements Closeable
throw new CommandNotSupportedException(Command.BROWSE);
}
/**
* Method description
*
*
* @return
*
* @since 1.43
*/
public BundleCommand getBundleCommand()
{
throw new CommandNotSupportedException(Command.BUNDLE);
}
/**
* Method description
*
@@ -218,4 +231,17 @@ public abstract class RepositoryServiceProvider implements Closeable
{
throw new CommandNotSupportedException(Command.TAGS);
}
/**
* Method description
*
*
* @return
*
* @since 1.43
*/
public UnbundleCommand getUnbundleCommand()
{
throw new CommandNotSupportedException(Command.UNBUNDLE);
}
}

View File

@@ -0,0 +1,67 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.api.UnbundleResponse;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
/**
* Service provider implementation for the unbundle command.
*
* @author Sebastian Sdorra <s.sdorra@gmail.com>
* @since 1.43
*/
public interface UnbundleCommand
{
/**
* The unbundle command can restore an empty repository from a bundle.
*
*
* @param request unbundle request
*
* @return unbundle response
*
* @throws IOException
* @throws RepositoryException
*/
public UnbundleResponse unbundle(UnbundleCommandRequest request)
throws IOException, RepositoryException;
}

View File

@@ -0,0 +1,110 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Objects;
import com.google.common.io.ByteSource;
/**
* Request object for the unbundle command.
*
* @author Sebastian Sdorra <s.sdorra@gmail.com>
* @since 1.43
*/
public final class UnbundleCommandRequest
{
/**
* Constructs a new unbundle command request.
*
*
* @param archive byte source archive
*/
public UnbundleCommandRequest(ByteSource archive)
{
this.archive = archive;
}
//~--- methods --------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final UnbundleCommandRequest other = (UnbundleCommandRequest) obj;
return Objects.equal(archive, other.archive);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode()
{
return Objects.hashCode(archive);
}
//~--- get methods ----------------------------------------------------------
/**
* Returns the archive as {@link ByteSource}.
*
*
* @return {@link ByteSource} archive
*/
ByteSource getArchive()
{
return archive;
}
//~--- fields ---------------------------------------------------------------
/** byte source archive */
private final ByteSource archive;
}

View File

@@ -94,6 +94,20 @@ public class RestUrlProvider implements UrlProvider
return HttpUtil.append(baseUrl, PART_AUTHENTICATION).concat(extension);
}
/**
* Method description
*
*
* @return
*
* @since 1.43
*/
@Override
public String getBaseUrl()
{
return baseUrl;
}
/**
* Method description
*

View File

@@ -48,6 +48,16 @@ public interface UrlProvider
*/
public String getAuthenticationUrl();
/**
* Method description
*
*
* @return
*
* @since 1.43
*/
public String getBaseUrl();
/**
* Method description
*
@@ -77,7 +87,7 @@ public interface UrlProvider
*
*
* @return
*
*
* @since 1.41
*/
public SecurityUrlProvider getSecurityUrlProvider();

View File

@@ -88,6 +88,20 @@ public class WUIUrlProvider implements UrlProvider
return baseUrl;
}
/**
* Method description
*
*
* @return
*
* @since 1.43
*/
@Override
public String getBaseUrl()
{
return baseUrl;
}
/**
* Method description
*

View File

@@ -73,6 +73,12 @@ public final class HttpUtil
/** Field description */
public static final String ENCODING = "UTF-8";
/**
* location header
* @since 1.43
*/
public static final String HEADER_LOCATION = "Location";
/**
* header for identifying the scm-manager client
* @since 1.19

View File

@@ -0,0 +1,111 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.web.filter;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Helper methods for implementations of the {@link AutoLoginModule}.
*
* @author Sebastian Sdorra <sebastian.sdorra@gmail.com>
*
* @since 1.42
*/
public final class AutoLoginModules
{
/** Field description */
private static final String FLAG_COMPLETE =
AutoLoginModules.class.getName().concat("complete");
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*/
private AutoLoginModules() {}
//~--- methods --------------------------------------------------------------
/**
* Mark the request as completed. No further actions will be executed.
*
* @param request http servlet request
*/
public static void markAsComplete(HttpServletRequest request)
{
request.setAttribute(FLAG_COMPLETE, Boolean.TRUE);
}
/**
* Sends a redirect to the specified url and marks the request as completed.
* This method is useful for SSO solutions which have to redirect the user
* to a central login page. This method must be used in favor of
* {@link HttpServletResponse#sendRedirect(java.lang.String)} which could
* result in an error.
*
* @param request http servlet request
* @param response http servlet response
* @param url redirect target
*
* @throws IOException if client could not be redirected
*/
public static void sendRedirect(HttpServletRequest request,
HttpServletResponse response, String url)
throws IOException
{
markAsComplete(request);
response.sendRedirect(url);
}
//~--- get methods ----------------------------------------------------------
/**
* Returns {@code true} is the request is marked as complete.
*
* @param request http servlet request
*
* @return {@code true} if request is complete
*/
public static boolean isComplete(HttpServletRequest request)
{
return request.getAttribute(FLAG_COMPLETE) != null;
}
}

View File

@@ -126,60 +126,17 @@ public class BasicAuthenticationFilter extends AutoLoginFilter
throws IOException, ServletException
{
Subject subject = SecurityUtils.getSubject();
// get authenticated user or process AutoLoginModule's
User user = getAuthenticatedUser(request, response);
// Fallback to basic authentication scheme
if (user == null)
if (AutoLoginModules.isComplete(request))
{
String authentication = request.getHeader(HEADER_AUTHORIZATION);
if (Util.startWithIgnoreCase(authentication, AUTHORIZATION_BASIC_PREFIX))
{
if (logger.isTraceEnabled())
{
logger.trace(
"found basic authorization header, start authentication");
}
user = authenticate(request, response, subject, authentication);
if (logger.isTraceEnabled())
{
if (user != null)
{
logger.trace("user {} successfully authenticated", user.getName());
}
else
{
logger.trace("authentcation failed, user object is null");
}
}
}
else if ((configuration != null)
&& configuration.isAnonymousAccessEnabled())
{
if (logger.isTraceEnabled())
{
logger.trace("anonymous access granted");
}
user = SCMContext.ANONYMOUS;
}
}
if (user == null)
{
if (logger.isTraceEnabled())
{
logger.trace("could not find user send unauthorized");
}
handleUnauthorized(request, response, chain);
logger.debug("request marked as complete from an auto login module");
}
else
{
chain.doFilter(new SecurityHttpServletRequestWrapper(request, user),
response);
// process with basic authentication
processRequest(request, response, chain, subject, user);
}
}
@@ -318,6 +275,79 @@ public class BasicAuthenticationFilter extends AutoLoginFilter
return user;
}
/**
* Method description
*
*
* @param request
* @param response
* @param chain
* @param subject
* @param user
*
* @throws IOException
* @throws ServletException
*/
private void processRequest(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Subject subject, User user)
throws IOException, ServletException
{
// Fallback to basic authentication scheme
if (user == null)
{
String authentication = request.getHeader(HEADER_AUTHORIZATION);
if (Util.startWithIgnoreCase(authentication, AUTHORIZATION_BASIC_PREFIX))
{
if (logger.isTraceEnabled())
{
logger.trace(
"found basic authorization header, start authentication");
}
user = authenticate(request, response, subject, authentication);
if (logger.isTraceEnabled())
{
if (user != null)
{
logger.trace("user {} successfully authenticated", user.getName());
}
else
{
logger.trace("authentcation failed, user object is null");
}
}
}
else if ((configuration != null)
&& configuration.isAnonymousAccessEnabled())
{
if (logger.isTraceEnabled())
{
logger.trace("anonymous access granted");
}
user = SCMContext.ANONYMOUS;
}
}
if (user == null)
{
if (logger.isTraceEnabled())
{
logger.trace("could not find user send unauthorized");
}
handleUnauthorized(request, response, chain);
}
else
{
chain.doFilter(new SecurityHttpServletRequestWrapper(request, user),
response);
}
}
//~--- fields ---------------------------------------------------------------
/** scm main configuration */

View File

@@ -39,7 +39,7 @@
<body>
<div style="text-align: justify;">
<p>
<img src="http://download.scm-manager.org/images/logo/scm-manager_logo.jpg" />
<img src="//download.scm-manager.org/images/logo/scm-manager_logo.jpg" alt="SCM-Manager" />
</p>
</div>
<p></p>
@@ -62,7 +62,7 @@
<h3>Architecture</h3>
<div style="text-align: center;">
<img src="http://download.scm-manager.org/images/architecture/architecture.001.png" alt="Architecture Overview">
<img src="//download.scm-manager.org/images/architecture/architecture.001.png" alt="Architecture Overview">
</div>
</body>
</html>

View File

@@ -33,4 +33,7 @@ http://bitbucket.org/sdorra/scm-manager
<extension-point>
<class>javax.servlet.ServletContextListener</class>
</extension-point>
<extension-point>
<class>javax.servlet.http.HttpSessionListener</class>
</extension-point>
</module>