incubator-ace-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject svn commit: r984544 - in /incubator/ace/trunk/ace-repository-ext: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/ace/ src/main/java/org/apache/ace/repository/ src/main/java/org/apache/ace/reposito...
Date Wed, 11 Aug 2010 19:23:56 GMT
Author: marrs
Date: Wed Aug 11 19:23:55 2010
New Revision: 984544

URL: http://svn.apache.org/viewvc?rev=984544&view=rev
Log:
Added another jar, containing repository implementations.

Added:
    incubator/ace/trunk/ace-repository-ext/
    incubator/ace/trunk/ace-repository-ext/pom.xml
    incubator/ace/trunk/ace-repository-ext/src/
    incubator/ace/trunk/ace-repository-ext/src/main/
    incubator/ace/trunk/ace-repository-ext/src/main/java/
    incubator/ace/trunk/ace-repository-ext/src/main/java/org/
    incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/
    incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/
    incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/
    incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/
    incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/BackupRepository.java
    incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/CachedRepository.java
    incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/
    incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/CachedRepositoryImpl.java
    incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/FilebasedBackupRepository.java
    incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/RemoteRepository.java

Added: incubator/ace/trunk/ace-repository-ext/pom.xml
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-repository-ext/pom.xml?rev=984544&view=auto
==============================================================================
--- incubator/ace/trunk/ace-repository-ext/pom.xml (added)
+++ incubator/ace/trunk/ace-repository-ext/pom.xml Wed Aug 11 19:23:55 2010
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <!--
+
+        Licensed to the Apache Software Foundation (ASF) under one or more
+        contributor license agreements.  See the NOTICE file distributed with
+        this work for additional information regarding copyright ownership.
+        The ASF licenses this file to You 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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ace</groupId>
+        <artifactId>ace-pom</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+        <relativePath>../pom/</relativePath>                
+    </parent>
+
+    <groupId>org.apache.ace</groupId>
+    <artifactId>ace-repository-ext</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+
+    <name>Apache ACE - Repository Extensions</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>ace-range-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>ace-repository-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>ace-util</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file

Added: incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/BackupRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/BackupRepository.java?rev=984544&view=auto
==============================================================================
--- incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/BackupRepository.java
(added)
+++ incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/BackupRepository.java
Wed Aug 11 19:23:55 2010
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ace.repository.ext;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Provides an interface for backing up objects. <code>write</code> and <code>read</code>
+ * allow writing and reading of the current version of the object. <code>backup</code>
+ * backs up the object, and <code>restore</code> restores it from a previously
backed up
+ * version, if any. There is no way to directly use the backup.
+ */
+public interface BackupRepository
+{
+
+    /**
+     * Writes the input stream to the current object.
+     * @param data The data to be written. Remember to close this stream, if necessary.
+     * @throws java.io.IOException Will be thrown when (a) the input stream gets closed
+     * unexpectedly, or (b) there is an error writing the data.
+     */
+    public void write(InputStream data) throws IOException;
+
+    /**
+     * Reads the input stream from the current object. If there is no current version,
+     * an empty stream will be returned.
+     * @return An input stream, from which can be read. Remember to close it.
+     * @throws java.io.IOException Will be thrown when there is a problem storing the data.
+     */
+    public InputStream read() throws IOException;
+
+    /**
+     * Restores a previously backuped version of the object.
+     * @return True when there was a previously backup version which has
+     * now been restored, false otherwise.
+     * @throws java.io.IOException Thrown when the restore process goes bad.
+     */
+    public boolean restore() throws IOException;
+
+    /**
+     * Backs up the current version of the object, overwriting a previous
+     * backup, if any.
+     * @return True when there was a current version to be backed up, false
+     * otherwise.
+     * @throws java.io.IOException Thrown when the restore process goes bad.
+     */
+    public boolean backup() throws IOException;
+
+}
\ No newline at end of file

Added: incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/CachedRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/CachedRepository.java?rev=984544&view=auto
==============================================================================
--- incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/CachedRepository.java
(added)
+++ incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/CachedRepository.java
Wed Aug 11 19:23:55 2010
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ace.repository.ext;
+
+import java.io.IOException;
+import java.io.InputStream;
+import org.apache.ace.repository.Repository;
+
+/**
+ * Provides a cached repository representation, allowing the storing of local changes, without
+ * committing them to the actual repository immediately.
+ */
+public interface CachedRepository extends Repository {
+
+    /**
+     * Checks our the most current version from the actual repository.
+     * @param fail Indicates that this method should throw an IOException when no data
+     * is available. Setting it to <code>false</code> will make it return an
+     * empty stream in that case.
+     * @return An input stream representing the checked out object.
+     * @throws java.io.IOException Is thrown when the actual repository's commit does.
+     */
+    public InputStream checkout(boolean fail) throws IOException;
+
+    /**
+     * Commits the most current version to the actual repository.
+     * @return true on success, false on failure (e.g. bad version number)
+     * @throws java.io.IOException Is thrown when the actual repository's commit does.
+     */
+    public boolean commit() throws IOException;
+
+    /**
+     * Gets the most recent version of the object. If no current version is available,
+     * and empty stream will be returned.
+     * @param fail Indicates that this method should throw an IOException when no data
+     * is available. Setting it to <code>false</code> will make it return an
+     * empty stream in that case.
+     * @return An input stream representing the most recently written object.
+     * @throws java.io.IOException Thrown when there is a problem retrieving the data.
+     */
+    public InputStream getLocal(boolean fail) throws IOException;
+
+    /**
+     * Writes the most recent version of the object.
+     * @throws java.io.IOException Thrown when there is a problem storing the data.
+     */
+    public void writeLocal(InputStream data) throws IOException;
+
+    /**
+     * Undoes all changes made using <code>writeLocal()</code> since the
+     * last <code>commit</code> or <code>checkout</code>.
+     * @throws java.io.IOException
+     */
+    public boolean revert() throws IOException;
+
+    /**
+     * Gets the most recent version of this repository, that is, the most recent version
+     * number that is either committed (successfully) or checked out.
+     * @return The most recent version of the underlying repository.
+     */
+    public long getMostRecentVersion();
+
+    /**
+     * Checks whether the version we have locally is current with respect to the version
+     * on the server.
+     * @return whether the version we have locally is current with respect to the version
+     * on the server.
+     * @throws java.io.IOException Thrown when an error occurs communicating with the server.
+     */
+    public boolean isCurrent() throws IOException;
+}
\ No newline at end of file

Added: incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/CachedRepositoryImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/CachedRepositoryImpl.java?rev=984544&view=auto
==============================================================================
--- incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/CachedRepositoryImpl.java
(added)
+++ incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/CachedRepositoryImpl.java
Wed Aug 11 19:23:55 2010
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ace.repository.ext.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.ace.range.RangeIterator;
+import org.apache.ace.range.SortedRangeSet;
+import org.apache.ace.repository.Repository;
+import org.apache.ace.repository.ext.BackupRepository;
+import org.apache.ace.repository.ext.CachedRepository;
+import org.osgi.service.useradmin.User;
+
+/**
+ * Provides a CachedRepository, which uses either a <code>Repository</code> and
a <code>BackupRepository</code>
+ * as remote and local storage, or a URL location and two files, from which it will create
a <code>Repository</code>
+ *  and a <code>FileBasedBackupRepository</code>. Note that this class is not
thread-safe, and should be synchronized
+ *  by the caller.
+ */
+public class CachedRepositoryImpl implements CachedRepository {
+    public static final long UNCOMMITTED_VERSION = -1;
+
+    private final User m_user;
+    private volatile long m_mostRecentVersion;
+
+    private final BackupRepository m_local;
+    private final Repository m_remote;
+
+    /**
+     * Creates a cached repository which uses <code>remote</code>, <code>customer</code>
and
+     * <code>name</code> to create a <code>RemoteRepository</code>,
and uses the <code>Files</code>s
+     * passed in as a for local storage and backup.
+     * @param user A user object, which is allowed to access <code>remote</code>.
+     * @param remote The location of the remote repository.
+     * @param customer The customer name to be used with the remote repository.
+     * @param name The name to be used with the remote repository.
+     * @param local A local file to be used for storage of changes to the repository.
+     * @param backup A local file to be used as a local backup of what was on the server.
+     * @param mostRecentVersion The version from which <code>backup</code> was
checked out or committed.
+     * If no version has been committed yet, use <code>UNCOMMITTED_VERSION</code>.
+     */
+    public CachedRepositoryImpl(User user, URL remote, String customer, String name, File
local, File backup, long mostRecentVersion) {
+        this(user,
+            new RemoteRepository(remote, customer, name),
+            new FilebasedBackupRepository(local, backup),
+            mostRecentVersion);
+    }
+
+    /**
+     * Creates a cached repository using.
+     * @param user A user object, which is allowed to access <code>remote</code>.
+     * @param remote A repository which holds committed versions.
+     * @param backup A backup repository for local changes.
+     * @param mostRecentVersion The version from which <code>backup</code> was
checked out or committed.
+     * If no version has been committed yet, use <code>UNCOMMITTED_VERSION</code>.
+     */
+    public CachedRepositoryImpl(User user, Repository remote, BackupRepository backup, long
mostRecentVersion) {
+        m_user = user;
+        m_remote = remote;
+        m_local = backup;
+        m_mostRecentVersion = mostRecentVersion;
+    }
+
+
+    public InputStream checkout(boolean fail) throws IOException, IllegalArgumentException
{
+        m_mostRecentVersion = highestRemoteVersion();
+        if (m_mostRecentVersion == 0) {
+            // If there is no remote version, then simply return an empty stream.
+            if (fail) {
+                throw new IOException("No version has yet been checked in to the repository.");
+            }
+            else {
+                return new ByteArrayInputStream(new byte[0]);
+            }
+        }
+        return checkout(m_mostRecentVersion);
+    }
+
+    public InputStream checkout(long version) throws IOException, IllegalArgumentException
{
+        m_local.write(m_remote.checkout(version));
+        m_local.backup();
+
+        m_mostRecentVersion = version;
+
+        return m_local.read();
+    }
+
+    public boolean commit(InputStream data, long fromVersion) throws IOException, IllegalArgumentException
{
+        m_local.write(data);
+
+        return commit(fromVersion);
+    }
+
+    public boolean commit() throws IOException {
+        if (m_mostRecentVersion < 0) {
+            throw new IllegalStateException("A commit should be preceded by a checkout.");
+        }
+        return commit(m_mostRecentVersion++);
+    }
+
+    public boolean commit(long fromVersion) throws IOException, IllegalArgumentException
{
+        boolean success = m_remote.commit(m_local.read(), fromVersion);
+        if (success) {
+            m_local.backup();
+        }
+
+        return success;
+    }
+
+    public SortedRangeSet getRange() throws IOException {
+        return m_remote.getRange();
+    }
+
+    public InputStream getLocal(boolean fail) throws IllegalArgumentException, IOException
{
+        if ((m_mostRecentVersion <= 0) && fail) {
+            throw new IOException("No local version available of " + m_local + ", remote
" + m_remote);
+        }
+        return m_local.read();
+    }
+
+    public boolean revert() throws IOException {
+         return m_local.restore();
+    }
+
+    public void writeLocal(InputStream data) throws IllegalArgumentException, IOException
{
+        m_local.write(data);
+    }
+
+    public long getMostRecentVersion() {
+        return m_mostRecentVersion;
+    }
+
+    public boolean isCurrent() throws IOException {
+        return highestRemoteVersion() == m_mostRecentVersion;
+    }
+
+    private long highestRemoteVersion() throws IOException {
+        long result = 0;
+        RangeIterator ri = getRange().iterator();
+        while (ri.hasNext()) {
+            result = ri.next();
+        }
+        return result;
+    }
+}
\ No newline at end of file

Added: incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/FilebasedBackupRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/FilebasedBackupRepository.java?rev=984544&view=auto
==============================================================================
--- incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/FilebasedBackupRepository.java
(added)
+++ incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/FilebasedBackupRepository.java
Wed Aug 11 19:23:55 2010
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ace.repository.ext.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.ace.repository.ext.BackupRepository;
+
+/**
+ * A file-based implementation of the Backup Repository, using two files to store the current
+ * and backup version.
+ */
+public class FilebasedBackupRepository implements BackupRepository {
+    private static final int COPY_BUFFER_SIZE = 4096;
+
+    private final File m_current;
+    private final File m_backup;
+
+    /**
+     * Creates a FilebasedBackupRepository. The file objects should point to a correct file,
+     * but the files will be created when necessary.
+     * @param current A file to store the current revision in.
+     * @param backup A file to store a backup version in.
+     */
+    public FilebasedBackupRepository(File current, File backup) {
+        m_current = current;
+        m_backup = backup;
+    }
+
+    public InputStream read() throws IOException {
+        if (!m_current.exists()) {
+            return new ByteArrayInputStream(new byte[0]);
+        }
+
+        try {
+            return new FileInputStream(m_current);
+        }
+        catch (FileNotFoundException e) {
+            throw new IOException("Unable to open file:" + e.getMessage());
+        }
+    }
+
+    public void write(InputStream data) throws IOException {
+        try {
+            if (!m_current.exists()) {
+                m_current.createNewFile();
+            }
+        }
+        catch (IOException e) {
+            throw new IOException("Unable to create file:" + e.getMessage());
+        }
+
+        try {
+            FileOutputStream out = new FileOutputStream(m_current);
+            copy(data, out);
+            out.close();
+        }
+        catch (FileNotFoundException e) {
+            throw new IOException("Unable to open file:" + e.getMessage());
+        }
+    }
+
+    public boolean backup() throws IOException {
+        if (!m_current.exists()) {
+            return false;
+        }
+        copy(m_current, m_backup);
+        return true;
+    }
+
+    public boolean restore() throws IOException {
+        if (!m_backup.exists()) {
+            return false;
+        }
+        copy(m_backup, m_current);
+        return true;
+    }
+
+    /**
+     * Helper function that writes the contents of one file to another.
+     * @param source The source file.
+     * @param destination The destination file.
+     * @throws java.io.IOException Thrown when file IO goes wrong.
+     */
+    private static void copy(File source, File destination) throws IOException {
+        if (destination.exists()) {
+            destination.delete();
+        }
+        destination.createNewFile();
+
+        FileOutputStream out = new FileOutputStream(destination);
+        FileInputStream in = new FileInputStream(source);
+
+        copy(in, out);
+        in.close();
+        out.close();
+    }
+
+    /**
+     * Copies the contents of an input stream to an output stream.
+     * @param in The input stream.
+     * @param out The output stream.
+     * @throws java.io.IOException Thrown when the output stream is closed unexpectedly.
+     */
+    private static void copy(InputStream in, OutputStream out) throws IOException {
+        byte[] buffer = new byte[COPY_BUFFER_SIZE];
+        int bytes = in.read(buffer);
+        while (bytes != -1) {
+            out.write(buffer, 0, bytes);
+            out.flush();
+            bytes = in.read(buffer);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "FilebasedBackupRepository[" + m_current + "," + m_backup + "]";
+    }
+}
\ No newline at end of file

Added: incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/RemoteRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/RemoteRepository.java?rev=984544&view=auto
==============================================================================
--- incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/RemoteRepository.java
(added)
+++ incubator/ace/trunk/ace-repository-ext/src/main/java/org/apache/ace/repository/ext/impl/RemoteRepository.java
Wed Aug 11 19:23:55 2010
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.ace.repository.ext.impl;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.ace.range.SortedRangeSet;
+import org.apache.ace.repository.Repository;
+
+/**
+ * This class works as a local interface for a remote repository by handling the network
+ * communication.
+ */
+public class RemoteRepository implements Repository {
+    private static final String COMMAND_QUERY = "/query";
+    private static final String COMMAND_CHECKOUT = "/checkout";
+    private static final String COMMAND_COMMIT = "/commit";
+    private static final String MIME_APPLICATION_OCTET_STREAM = "application/octet-stream";
+    private static final int COPY_BUFFER_SIZE = 4096;
+
+    private final URL m_url;
+    private final String m_customer;
+    private final String m_name;
+    private final String m_filter;
+
+
+    RemoteRepository(URL url, String customer, String name, String filter) {
+        m_url = url;
+        m_customer = customer;
+        m_name = name;
+        m_filter = filter;
+    }
+
+    /**
+     * Creates a remote repository that connects to a given location with a given customer-
+     * and repository name.
+     * @param url The location of the repository.
+     * @param customer The customer name to use.
+     * @param name The repository name to use.
+     */
+    public RemoteRepository(URL url, String customer, String name) {
+        this(url, customer, name, null);
+    }
+
+    /**
+     * Creates a remote repository that connects to a given location with a given filter.
+     * @param url The location of the repository.
+     * @param filter An LDAP filter string to select the repository.
+     */
+    public RemoteRepository(URL url, String filter) {
+        this(url, null, null, filter);
+    }
+
+
+    public InputStream checkout(long version) throws IOException, IllegalArgumentException
{
+        if (version <= 0) {
+            throw new IllegalArgumentException("Version must be greater than 0.");
+        }
+
+        URL url = buildCommand(m_url, COMMAND_CHECKOUT, version);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        if (connection.getResponseCode() == HttpServletResponse.SC_NOT_FOUND) {
+            throw new IllegalArgumentException("Requested version not found in remote repository.
(" + connection.getResponseMessage() + ")");
+        }
+        if (connection.getResponseCode() != HttpServletResponse.SC_OK) {
+            throw new IOException("Connection error: " + connection.getResponseMessage());
+        }
+
+        return connection.getInputStream();
+    }
+
+    public boolean commit(InputStream data, long fromVersion) throws IOException, IllegalArgumentException
{
+        URL url = buildCommand(m_url, COMMAND_COMMIT, fromVersion);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        connection.setDoOutput(true);
+        connection.setRequestProperty("Content-Type", MIME_APPLICATION_OCTET_STREAM);
+
+        OutputStream out = connection.getOutputStream();
+        copy(data, out);
+        out.flush();
+        out.close();
+        return connection.getResponseCode() == HttpServletResponse.SC_OK;
+    }
+
+    public SortedRangeSet getRange() throws IOException {
+        URL url = buildCommand(m_url, COMMAND_QUERY, 0);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        if (connection.getResponseCode() == HttpServletResponse.SC_OK) {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+            String line = reader.readLine();
+            if (line == null) {
+                throw new IOException("Repository not found: customer=" + m_customer + ",
name=" + m_name);
+            }
+            String representation = line.substring(line.lastIndexOf(','));
+            reader.close();
+            return new SortedRangeSet(representation);
+        }
+        throw new IOException("Connection error: " + connection.getResponseMessage());
+    }
+
+    /**
+     * Helper method which copies the contents of an input stream to an output stream.
+     * @param in The input stream.
+     * @param out The output stream.
+     * @throws java.io.IOException Thrown when one of the streams is closed unexpectedly.
+     */
+    private static void copy(InputStream in, OutputStream out) throws IOException {
+        byte[] buffer = new byte[COPY_BUFFER_SIZE];
+        int bytes = in.read(buffer);
+        while (bytes != -1) {
+            out.write(buffer, 0, bytes);
+            bytes = in.read(buffer);
+        }
+    }
+
+    /**
+     * Builds a command string to use in the request to the server, based on the parameters
+     * this object was created with. The version is only mandatory for <code>CHECKOUT</code>
+     * and <code>COMMIT</code>.
+     * @param command A command string, use the <code>COMMAND_</code> constants
in this file.
+     * @param version A version statement.
+     * @return The command string.
+     */
+    private URL buildCommand(URL url, String command, long version) {
+        StringBuffer result = new StringBuffer();
+
+        if (m_filter != null) {
+            result.append(m_filter);
+        }
+        else {
+
+            if (m_customer != null) {
+                if (result.length() != 0) {
+                    result.append("&");
+                }
+                result.append("customer=").append(m_customer);
+            }
+            if (m_name != null) {
+                if (result.length() != 0) {
+                    result.append("&");
+                }
+                result.append("name=").append(m_name);
+            }
+            if (command != COMMAND_QUERY) {
+                if (result.length() != 0) {
+                    result.append("&");
+                }
+                result.append("version=").append(version);
+            }
+        }
+
+        try {
+            if (result.length() > 0) {
+                return new URL(url.toString() + command + "?" + result.toString());
+            }
+            else {
+                return new URL(url.toString() + command);
+            }
+        }
+        catch (MalformedURLException e) {
+            throw new IllegalArgumentException("Could not create URL: " + e.getMessage());
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "RemoteRepository[" + m_url + "," + m_customer + "," + m_name + "," + m_filter
+ "]";
+    }
+}
\ No newline at end of file



Mime
View raw message