Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/CliUtils.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,57 @@ +/* + * 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.jackrabbit.oak.upgrade.cli; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.io.Closer; + +public class CliUtils { + + private static final Logger log = LoggerFactory.getLogger(OakUpgrade.class); + + public static void displayUsage() throws IOException { + System.out.println(getUsage().replace("${command}", "java -jar oak-run-*-jr2.jar upgrade")); + } + + public static String getUsage() throws IOException { + InputStream is = CliUtils.class.getClassLoader().getResourceAsStream("upgrade_usage.txt"); + try { + return IOUtils.toString(is); + } finally { + IOUtils.closeQuietly(is); + } + } + + public static void handleSigInt(final Closer closer) { + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + try { + closer.close(); + } catch (IOException e) { + log.error("Can't close", e); + } + } + }); + } +}
Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/MigrationFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/MigrationFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/MigrationFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/MigrationFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,123 @@ +/* + * 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.jackrabbit.oak.upgrade.cli; + +import java.io.IOException; +import java.util.Iterator; +import java.util.ServiceLoader; + +import javax.jcr.RepositoryException; + +import org.apache.jackrabbit.core.RepositoryContext; +import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; +import org.apache.jackrabbit.oak.spi.commit.CommitHook; +import org.apache.jackrabbit.oak.spi.state.NodeStore; +import org.apache.jackrabbit.oak.upgrade.RepositorySidegrade; +import org.apache.jackrabbit.oak.upgrade.RepositoryUpgrade; +import org.apache.jackrabbit.oak.upgrade.cli.parser.CliArgumentException; +import org.apache.jackrabbit.oak.upgrade.cli.parser.DatastoreArguments; +import org.apache.jackrabbit.oak.upgrade.cli.parser.MigrationOptions; +import org.apache.jackrabbit.oak.upgrade.cli.parser.StoreArguments; + +import com.google.common.collect.ImmutableList; +import com.google.common.io.Closer; + +public class MigrationFactory { + + protected final MigrationOptions options; + + protected final StoreArguments stores; + + protected final DatastoreArguments datastores; + + protected final Closer closer; + + public MigrationFactory(MigrationOptions options, StoreArguments stores, DatastoreArguments datastores, Closer closer) { + this.options = options; + this.stores = stores; + this.datastores = datastores; + this.closer = closer; + } + + public RepositoryUpgrade createUpgrade() throws IOException, RepositoryException, CliArgumentException { + RepositoryContext src = stores.getSrcStore().create(closer); + BlobStore srcBlobStore = new DataStoreBlobStore(src.getDataStore()); + NodeStore dstStore = createTarget(closer, srcBlobStore); + return createUpgrade(src, dstStore); + } + + public RepositorySidegrade createSidegrade() throws IOException, CliArgumentException { + BlobStore srcBlobStore = datastores.getSrcBlobStore().create(closer); + NodeStore srcStore = stores.getSrcStore().create(srcBlobStore, closer); + NodeStore dstStore = createTarget(closer, srcBlobStore); + return createSidegrade(srcStore, dstStore); + } + + protected NodeStore createTarget(Closer closer, BlobStore srcBlobStore) throws IOException { + BlobStore dstBlobStore = datastores.getDstBlobStore(srcBlobStore).create(closer); + NodeStore dstStore = stores.getDstStore().create(dstBlobStore, closer); + return dstStore; + } + + protected RepositoryUpgrade createUpgrade(RepositoryContext source, NodeStore dstStore) { + RepositoryUpgrade upgrade = new RepositoryUpgrade(source, dstStore); + upgrade.setCopyBinariesByReference(datastores.getBlobMigrationCase() == DatastoreArguments.BlobMigrationCase.COPY_REFERENCES); + upgrade.setCopyVersions(options.getCopyVersions()); + upgrade.setCopyOrphanedVersions(options.getCopyOrphanedVersions()); + if (options.getIncludePaths() != null) { + upgrade.setIncludes(options.getIncludePaths()); + } + if (options.getExcludePaths() != null) { + upgrade.setExcludes(options.getExcludePaths()); + } + if (options.getMergePaths() != null) { + upgrade.setMerges(options.getMergePaths()); + } + upgrade.setFilterLongNames(!stores.getDstType().isSupportLongNames()); + upgrade.setCheckLongNames(!options.isSkipNameCheck() && !stores.getDstType().isSupportLongNames()); + upgrade.setSkipOnError(!options.isFailOnError()); + upgrade.setEarlyShutdown(options.isEarlyShutdown()); + upgrade.setSkipInitialization(options.isSkipInitialization()); + ServiceLoader<CommitHook> loader = ServiceLoader.load(CommitHook.class); + Iterator<CommitHook> iterator = loader.iterator(); + ImmutableList.Builder<CommitHook> builder = ImmutableList.<CommitHook> builder().addAll(iterator); + upgrade.setCustomCommitHooks(builder.build()); + return upgrade; + } + + private RepositorySidegrade createSidegrade(NodeStore srcStore, NodeStore dstStore) { + RepositorySidegrade sidegrade = new RepositorySidegrade(srcStore, dstStore); + sidegrade.setCopyVersions(options.getCopyVersions()); + sidegrade.setCopyOrphanedVersions(options.getCopyOrphanedVersions()); + if (options.getIncludePaths() != null) { + sidegrade.setIncludes(options.getIncludePaths()); + } + if (options.getExcludePaths() != null) { + sidegrade.setExcludes(options.getExcludePaths()); + } + if (options.getMergePaths() != null) { + sidegrade.setMerges(options.getMergePaths()); + } + sidegrade.setFilterLongNames(stores.getSrcType().isSupportLongNames() && !stores.getDstType().isSupportLongNames()); + sidegrade.setVerify(options.isVerify()); + sidegrade.setOnlyVerify(options.isOnlyVerify()); + sidegrade.setSkipCheckpoints(options.isSkipCheckpoints()); + return sidegrade; + } + +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/OakUpgrade.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,101 @@ +/* + * 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.jackrabbit.oak.upgrade.cli; + +import java.io.IOException; +import java.util.List; +import java.util.ServiceLoader; + +import javax.jcr.RepositoryException; + +import com.google.common.collect.Lists; +import com.google.common.io.Closer; + +import joptsimple.OptionSet; +import org.apache.jackrabbit.oak.spi.lifecycle.CompositeInitializer; +import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer; +import org.apache.jackrabbit.oak.upgrade.cli.parser.CliArgumentException; +import org.apache.jackrabbit.oak.upgrade.cli.parser.DatastoreArguments; +import org.apache.jackrabbit.oak.upgrade.cli.parser.MigrationCliArguments; +import org.apache.jackrabbit.oak.upgrade.cli.parser.MigrationOptions; +import org.apache.jackrabbit.oak.upgrade.cli.parser.OptionParserFactory; +import org.apache.jackrabbit.oak.upgrade.cli.parser.StoreArguments; + +public class OakUpgrade { + + public static void main(String... args) throws IOException { + OptionSet options = OptionParserFactory.create().parse(args); + try { + MigrationCliArguments cliArguments = new MigrationCliArguments(options); + if (cliArguments.hasOption(OptionParserFactory.HELP) || cliArguments.getArguments().isEmpty()) { + CliUtils.displayUsage(); + return; + } + migrate(cliArguments); + } catch(CliArgumentException e) { + if (e.getMessage() != null) { + System.err.println(e.getMessage()); + } + System.exit(e.getExitCode()); + } + } + + public static void migrate(MigrationCliArguments argumentParser) throws IOException, CliArgumentException { + MigrationOptions options = new MigrationOptions(argumentParser); + options.logOptions(); + + StoreArguments stores = new StoreArguments(options, argumentParser.getArguments()); + stores.logOptions(); + + boolean srcEmbedded = stores.srcUsesEmbeddedDatastore(); + DatastoreArguments datastores = new DatastoreArguments(options, stores, srcEmbedded); + + migrate(options, stores, datastores); + } + + public static void migrate(MigrationOptions options, StoreArguments stores, DatastoreArguments datastores) throws IOException, CliArgumentException { + Closer closer = Closer.create(); + CliUtils.handleSigInt(closer); + MigrationFactory factory = new MigrationFactory(options, stores, datastores, closer); + try { + if (stores.getSrcStore().isJcr2()) { + upgrade(factory); + } else { + sidegrade(factory); + } + } catch (Throwable t) { + throw closer.rethrow(t); + } finally { + closer.close(); + } + } + + private static void upgrade(MigrationFactory migrationFactory) throws IOException, RepositoryException, CliArgumentException { + migrationFactory.createUpgrade().copy(createCompositeInitializer()); + } + + private static void sidegrade(MigrationFactory migrationFactory) throws IOException, RepositoryException, CliArgumentException { + migrationFactory.createSidegrade().copy(); + } + + private static RepositoryInitializer createCompositeInitializer() { + ServiceLoader<RepositoryInitializer> loader = ServiceLoader.load(RepositoryInitializer.class); + List<RepositoryInitializer> initializers = Lists.newArrayList(loader.iterator()); + return new CompositeInitializer(initializers); + } + +} \ No newline at end of file Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/BlobStoreFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/BlobStoreFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/BlobStoreFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/BlobStoreFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,27 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.blob; + +import java.io.IOException; + +import org.apache.jackrabbit.oak.spi.blob.BlobStore; + +import com.google.common.io.Closer; + +public interface BlobStoreFactory { + BlobStore create(Closer closer) throws IOException; +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/ConstantBlobStoreFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/ConstantBlobStoreFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/ConstantBlobStoreFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/ConstantBlobStoreFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,36 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.blob; + +import com.google.common.io.Closer; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; + +import java.io.IOException; + +public class ConstantBlobStoreFactory implements BlobStoreFactory { + + private final BlobStore blobStore; + + public ConstantBlobStoreFactory(BlobStore blobStore) { + this.blobStore = blobStore; + } + + @Override + public BlobStore create(Closer closer) throws IOException { + return blobStore; + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/DummyBlobStoreFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/DummyBlobStoreFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/DummyBlobStoreFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/DummyBlobStoreFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,34 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.blob; + +import org.apache.jackrabbit.oak.spi.blob.BlobStore; + +import com.google.common.io.Closer; + +public class DummyBlobStoreFactory implements BlobStoreFactory { + + @Override + public BlobStore create(Closer closer) { + return null; + } + + @Override + public String toString() { + return "DummyBlobStore"; + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileBlobStoreFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileBlobStoreFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileBlobStoreFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileBlobStoreFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,41 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.blob; + +import org.apache.jackrabbit.oak.spi.blob.BlobStore; +import org.apache.jackrabbit.oak.spi.blob.FileBlobStore; + +import com.google.common.io.Closer; + +public class FileBlobStoreFactory implements BlobStoreFactory { + + private final String directory; + + public FileBlobStoreFactory(String directory) { + this.directory = directory; + } + + @Override + public BlobStore create(Closer closer) { + return new FileBlobStore(directory); + } + + @Override + public String toString() { + return String.format("FileBlobStore[%s]", directory); + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileDataStoreFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileDataStoreFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileDataStoreFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/FileDataStoreFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,67 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.blob; + +import java.io.Closeable; +import java.io.IOException; + +import org.apache.jackrabbit.core.data.FileDataStore; +import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore; +import org.apache.jackrabbit.oak.plugins.blob.datastore.OakFileDataStore; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; + +import com.google.common.io.Closer; + +public class FileDataStoreFactory implements BlobStoreFactory { + + private final String directory; + + private final boolean ignoreMissingBlobs; + + public FileDataStoreFactory(String directory, boolean ignoreMissingBlobs) { + this.directory = directory; + this.ignoreMissingBlobs = ignoreMissingBlobs; + } + + @Override + public BlobStore create(Closer closer) { + OakFileDataStore delegate = new OakFileDataStore(); + delegate.setPath(directory); + delegate.init(null); + closer.register(asCloseable(delegate)); + + if (ignoreMissingBlobs) { + return new SafeDataStoreBlobStore(delegate); + } else { + return new DataStoreBlobStore(delegate); + } + } + + private static Closeable asCloseable(final FileDataStore store) { + return new Closeable() { + @Override + public void close() throws IOException { + store.close(); + } + }; + } + + @Override + public String toString() { + return String.format("FileDataStore[%s]", directory); + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/MissingBlobStore.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/MissingBlobStore.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/MissingBlobStore.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/MissingBlobStore.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,68 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.blob; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.jackrabbit.oak.spi.blob.BlobStore; + +/** + * Utility BlobStore implementation to be used in tooling that can work with a + * FileStore without the need of the DataStore being present locally + */ +public class MissingBlobStore implements BlobStore { + + @Override + public String writeBlob(InputStream in) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public int readBlob(String blobId, long pos, byte[] buff, int off, + int length) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public long getBlobLength(String blobId) throws IOException { + // best effort length extraction + int indexOfSep = blobId.lastIndexOf("#"); + if (indexOfSep != -1) { + return Long.valueOf(blobId.substring(indexOfSep + 1)); + } + return -1; + } + + @Override + public InputStream getInputStream(String blobId) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public String getBlobId(String reference) { + return reference; + } + + @Override + public String getReference(String blobId) { + return blobId; + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/MissingBlobStoreFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/MissingBlobStoreFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/MissingBlobStoreFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/MissingBlobStoreFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,34 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.blob; + +import org.apache.jackrabbit.oak.spi.blob.BlobStore; + +import com.google.common.io.Closer; + +public class MissingBlobStoreFactory implements BlobStoreFactory { + + @Override + public BlobStore create(Closer closer) { + return new MissingBlobStore(); + } + + @Override + public String toString() { + return "MissingBlobStore"; + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/S3DataStoreFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/S3DataStoreFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/S3DataStoreFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/S3DataStoreFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,127 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.blob; + +import java.io.Closeable; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.HashSet; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.jcr.RepositoryException; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.jackrabbit.aws.ext.ds.S3DataStore; +import org.apache.jackrabbit.core.data.CachingDataStore; +import org.apache.jackrabbit.core.data.DataStoreException; +import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.io.Closer; +import com.google.common.io.Files; + +public class S3DataStoreFactory implements BlobStoreFactory { + + private static final Logger log = LoggerFactory.getLogger(S3DataStoreFactory.class); + + private static final Pattern STRIP_VALUE_PATTERN = Pattern.compile("^[TILFDXSCB]?\"(.*)\"\\W*$"); + + private final Properties props; + + private final String directory; + + private final File tempHomeDir; + + private final boolean ignoreMissingBlobs; + + public S3DataStoreFactory(String configuration, String directory, boolean ignoreMissingBlobs) throws IOException { + this.props = new Properties(); + FileReader reader = new FileReader(new File(configuration)); + try { + props.load(reader); + } finally { + IOUtils.closeQuietly(reader); + } + + for (Object key : new HashSet<Object>(props.keySet())) { + String value = props.getProperty((String) key); + props.put(key, stripValue(value)); + } + + this.directory = directory; + this.tempHomeDir = Files.createTempDir(); + this.ignoreMissingBlobs = ignoreMissingBlobs; + } + + @Override + public BlobStore create(Closer closer) throws IOException { + S3DataStore delegate = new S3DataStore(); + delegate.setProperties(props); + delegate.setPath(directory); + try { + delegate.init(tempHomeDir.getPath()); + } catch (RepositoryException e) { + throw new IOException(e); + } + closer.register(asCloseable(delegate, tempHomeDir)); + if (ignoreMissingBlobs) { + return new SafeDataStoreBlobStore(delegate); + } else { + return new DataStoreBlobStore(delegate); + } + } + + private static Closeable asCloseable(final CachingDataStore store, final File tempHomeDir) { + return new Closeable() { + @Override + public void close() throws IOException { + try { + while (!store.getPendingUploads().isEmpty()) { + log.info("Waiting for following uploads to finish: " + store.getPendingUploads()); + Thread.sleep(1000); + } + store.close(); + FileUtils.deleteDirectory(tempHomeDir); + } catch (DataStoreException e) { + throw new IOException(e); + } catch (InterruptedException e) { + throw new IOException(e); + } + } + }; + } + + static String stripValue(String value) { + Matcher matcher = STRIP_VALUE_PATTERN.matcher(value); + if (matcher.matches()) { + return matcher.group(1); + } else { + return value; + } + } + + @Override + public String toString() { + return String.format("S3DataStore[%s]", directory); + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/SafeDataStoreBlobStore.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/SafeDataStoreBlobStore.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/SafeDataStoreBlobStore.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/blob/SafeDataStoreBlobStore.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,101 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.blob; + +import org.apache.jackrabbit.core.data.DataIdentifier; +import org.apache.jackrabbit.core.data.DataRecord; +import org.apache.jackrabbit.core.data.DataStore; +import org.apache.jackrabbit.core.data.DataStoreException; +import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore; +import org.apache.jackrabbit.oak.plugins.blob.datastore.InMemoryDataRecord; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * This implementation of the DataStoreBlobStore won't throw an exception if + * it can't find blob with given id. The WARN message will be emitted instead + * and the empty InputStream will be returned. + */ +public class SafeDataStoreBlobStore extends DataStoreBlobStore { + + private static final Logger log = LoggerFactory.getLogger(SafeDataStoreBlobStore.class); + + public SafeDataStoreBlobStore(DataStore delegate) { + super(delegate); + } + + @Override + public String getReference(@Nonnull String encodedBlobId) { + checkNotNull(encodedBlobId); + String blobId = extractBlobId(encodedBlobId); + //Reference are not created for in memory record + if (InMemoryDataRecord.isInstance(blobId)) { + return null; + } + + DataRecord record; + try { + record = delegate.getRecordIfStored(new DataIdentifier(blobId)); + if (record != null) { + return record.getReference(); + } else { + log.debug("No blob found for id [{}]", blobId); + } + } catch (DataStoreException e) { + log.warn("Unable to access the blobId for [{}]", blobId, e); + } + return null; + } + + + @Override + protected InputStream getStream(String blobId) throws IOException { + try { + DataRecord record = getDataRecord(blobId); + if (record == null) { + log.warn("No blob found for id [{}]", blobId); + return new ByteArrayInputStream(new byte[0]); + } + InputStream in = getDataRecord(blobId).getStream(); + if (!(in instanceof BufferedInputStream)){ + in = new BufferedInputStream(in); + } + return in; + } catch (DataStoreException e) { + throw new IOException(e); + } + } + + @Override + protected DataRecord getDataRecord(String blobId) throws DataStoreException { + DataRecord id; + if (InMemoryDataRecord.isInstance(blobId)) { + id = InMemoryDataRecord.getInstance(blobId); + } else { + id = delegate.getRecordIfStored(new DataIdentifier(blobId)); + } + return id; + } +} \ No newline at end of file Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/Jackrabbit2Factory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/Jackrabbit2Factory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/Jackrabbit2Factory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/Jackrabbit2Factory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,107 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.node; + +import java.io.BufferedReader; +import java.io.Closeable; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; + +import javax.jcr.RepositoryException; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.jackrabbit.core.RepositoryContext; +import org.apache.jackrabbit.core.config.RepositoryConfig; + +import com.google.common.io.Closer; + +public class Jackrabbit2Factory { + + private final File repositoryDir; + + private final File repositoryFile; + + public Jackrabbit2Factory(String repositoryDir, String repositoryFile) { + if (!isJcr2Repository(repositoryDir)) { + throw new IllegalArgumentException("Repository directory not found: " + repositoryDir); + } + this.repositoryDir = new File(repositoryDir); + this.repositoryFile = new File(repositoryFile); + if (!isRepositoryXml(repositoryFile)) { + throw new IllegalArgumentException("Repository configuration not found: " + repositoryFile); + } + } + + public RepositoryContext create(Closer closer) throws RepositoryException { + RepositoryContext source = RepositoryContext.create(RepositoryConfig.create(repositoryFile, repositoryDir)); + closer.register(asCloseable(source)); + return source; + } + + public File getRepositoryDir() { + return repositoryDir; + } + + private static Closeable asCloseable(final RepositoryContext context) { + return new Closeable() { + @Override + public void close() throws IOException { + context.getRepository().shutdown(); + } + }; + } + + public static boolean isRepositoryXml(String path) { + File file = new File(path); + if (file.isFile()) { + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(file)); + String line; + while ((line = reader.readLine()) != null) { + if (StringUtils.containsIgnoreCase(line, "<Repository>")) { + return true; + } + } + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + return false; + } finally { + IOUtils.closeQuietly(reader); + } + } + return false; + } + + public static boolean isJcr2Repository(String directory) { + File dir = new File(directory); + if (!dir.isDirectory()) { + return false; + } + File workspaces = new File(dir, "workspaces"); + return workspaces.isDirectory(); + } + + @Override + public String toString() { + return String.format("JCR2[%s, %s]", repositoryDir, repositoryFile); + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/JdbcFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/JdbcFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/JdbcFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/JdbcFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,102 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.node; + +import org.apache.jackrabbit.oak.plugins.document.DocumentMK; +import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore; +import org.apache.jackrabbit.oak.plugins.document.rdb.RDBBlobStore; +import org.apache.jackrabbit.oak.plugins.document.rdb.RDBDataSourceFactory; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; +import org.apache.jackrabbit.oak.spi.state.NodeStore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.io.Closer; + +import javax.sql.DataSource; +import java.io.Closeable; +import java.io.IOException; + +public class JdbcFactory implements NodeStoreFactory { + + private static final Logger log = LoggerFactory.getLogger(JdbcFactory.class); + + private final String jdbcUri; + + private final int cacheSize; + + private final String user; + + private final String password; + + private final boolean readOnly; + + public JdbcFactory(String jdbcUri, int cacheSize, String user, String password, boolean readOnly) { + this.jdbcUri = jdbcUri; + this.cacheSize = cacheSize; + if (user == null || password == null) { + throw new IllegalArgumentException("RBD requires username and password parameters."); + } + this.user = user; + this.password = password; + this.readOnly = readOnly; + } + + @Override + public NodeStore create(BlobStore blobStore, Closer closer) { + DocumentMK.Builder builder = MongoFactory.getBuilder(cacheSize); + if (blobStore != null) { + builder.setBlobStore(blobStore); + } + builder.setRDBConnection(getDataSource(closer)); + if (readOnly) { + log.warn("Read-only mode for the DocumentMK is not available in 1.4"); + } + log.info("Initialized DocumentNodeStore on RDB with Cache size : {} MB, Fast migration : {}", cacheSize, + builder.isDisableBranches()); + DocumentNodeStore documentNodeStore = builder.getNodeStore(); + closer.register(MongoFactory.asCloseable(documentNodeStore)); + return documentNodeStore; + } + + private DataSource getDataSource(Closer closer) { + DataSource ds = RDBDataSourceFactory.forJdbcUrl(jdbcUri, user, password); + if (ds instanceof Closeable) { + closer.register((Closeable)ds); + } + return ds; + } + + @Override + public boolean hasExternalBlobReferences() throws IOException { + Closer closer = Closer.create(); + try { + DataSource ds = getDataSource(closer); + RDBBlobStore blobStore = new RDBBlobStore(ds); + return !blobStore.getAllChunkIds(0).hasNext(); + } catch(Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + @Override + public String toString() { + return String.format("DocumentNodeStore[%s]", jdbcUri); + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/MongoFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/MongoFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/MongoFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/MongoFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,126 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.node; + +import com.mongodb.DB; +import org.apache.jackrabbit.oak.plugins.document.DocumentMK; +import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore; +import org.apache.jackrabbit.oak.plugins.document.mongo.MongoBlobStore; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; +import org.apache.jackrabbit.oak.spi.state.NodeStore; + +import com.google.common.io.Closer; +import com.mongodb.MongoClient; +import com.mongodb.MongoClientURI; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Closeable; +import java.io.IOException; +import java.net.UnknownHostException; + +public class MongoFactory implements NodeStoreFactory { + + private static final Logger log = LoggerFactory.getLogger(MongoFactory.class); + + private static final long MB = 1024 * 1024; + + private final MongoClientURI uri; + + private final int cacheSize; + + private final boolean readOnly; + + public MongoFactory(String repoDesc, int cacheSize, boolean readOnly) { + this.uri = new MongoClientURI(repoDesc); + this.cacheSize = cacheSize; + this.readOnly = readOnly; + } + + @Override + public NodeStore create(BlobStore blobStore, Closer closer) throws UnknownHostException { + DocumentMK.Builder builder = getBuilder(cacheSize); + builder.setMongoDB(getDB(closer)); + if (blobStore != null) { + builder.setBlobStore(blobStore); + } + if (readOnly) { + log.warn("Read-only mode for the DocumentMK is not available in 1.4"); + } + DocumentNodeStore documentNodeStore = builder.getNodeStore(); + closer.register(asCloseable(documentNodeStore)); + return documentNodeStore; + } + + private DB getDB(Closer closer) throws UnknownHostException { + String db; + if (uri.getDatabase() == null) { + db = "aem-author"; // assume an author instance + } else { + db = uri.getDatabase(); + } + MongoClient client = new MongoClient(uri); + closer.register(asCloseable(client)); + return client.getDB(db); + } + + @Override + public boolean hasExternalBlobReferences() throws IOException { + Closer closer = Closer.create(); + try { + MongoBlobStore mongoBlobStore = new MongoBlobStore(getDB(closer)); + return !mongoBlobStore.getAllChunkIds(0).hasNext(); + } catch(Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + static Closeable asCloseable(final DocumentNodeStore documentNodeStore) { + return new Closeable() { + @Override + public void close() throws IOException { + documentNodeStore.dispose(); + } + }; + } + + private static Closeable asCloseable(final MongoClient client) { + return new Closeable() { + @Override + public void close() throws IOException { + client.close(); + } + }; + } + + static DocumentMK.Builder getBuilder(int cacheSize) { + boolean fastMigration = !Boolean.getBoolean("mongomk.disableFastMigration"); + DocumentMK.Builder builder = new DocumentMK.Builder(); + builder.memoryCacheSize(cacheSize * MB); + if (fastMigration) { + builder.disableBranches(); + } + return builder; + } + + @Override + public String toString() { + return String.format("DocumentNodeStore[%s]", uri.toString()); + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/NodeStoreFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/NodeStoreFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/NodeStoreFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/NodeStoreFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,31 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.node; + +import java.io.IOException; + +import org.apache.jackrabbit.oak.spi.blob.BlobStore; +import org.apache.jackrabbit.oak.spi.state.NodeStore; + +import com.google.common.io.Closer; + +public interface NodeStoreFactory { + + NodeStore create(BlobStore blobStore, Closer closer) throws IOException; + + boolean hasExternalBlobReferences() throws IOException; +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/SegmentFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,129 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.node; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; + +import org.apache.jackrabbit.oak.plugins.blob.ReferenceCollector; +import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore; +import org.apache.jackrabbit.oak.plugins.segment.file.FileStore; +import org.apache.jackrabbit.oak.plugins.segment.file.FileStore.Builder; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; +import org.apache.jackrabbit.oak.spi.state.NodeState; +import org.apache.jackrabbit.oak.spi.state.NodeStore; + +import com.google.common.io.Closer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; + +public class SegmentFactory implements NodeStoreFactory { + + private static final Logger LOG = LoggerFactory.getLogger(SegmentFactory.class); + + private final File dir; + + private final boolean disableMmap; + + public SegmentFactory(String directory, boolean disableMmap, boolean readOnly) { + this.dir = new File(directory); + this.disableMmap = disableMmap; + createDirectoryIfMissing(dir); + if (readOnly) { + LOG.info("Read-only segment node store is not supported in 1.0"); + } + if (!dir.isDirectory()) { + throw new IllegalArgumentException("Not a directory: " + dir.getPath()); + } + } + + private void createDirectoryIfMissing(File directory) { + if (!directory.exists()) { + directory.mkdirs(); + } + } + + @Override + public NodeStore create(BlobStore blobStore, Closer closer) throws IOException { + File directory = new File(dir, "segmentstore"); + boolean mmapEnabled = !disableMmap && "64".equals(System.getProperty("sun.arch.data.model", "32")); + + final FileStore fs; + Builder builder; + builder = FileStore.newFileStore(directory); + + if (blobStore != null) { + builder.withBlobStore(blobStore); + } + builder.withMaxFileSize(256); + builder.withMemoryMapping(mmapEnabled); + fs = builder.create(); + + closer.register(asCloseable(fs)); + + return new TarNodeStore(new SegmentNodeStore(fs), new TarNodeStore.SuperRootProvider() { + @Override + public NodeState getSuperRoot() { + return fs.getHead(); + } + }); + } + + @Override + public boolean hasExternalBlobReferences() throws IOException { + FileStore fs = FileStore.newFileStore(new File(dir, "segmentstore")).create(); + try { + fs.getTracker().collectBlobReferences(new ReferenceCollector() { + @Override + public void addReference(String reference) { + // FIXME the collector should allow to stop processing + // see java.nio.file.FileVisitor + throw new ExternalBlobFound(); + } + }); + return false; + } catch (ExternalBlobFound e) { + return true; + } finally { + fs.close(); + } + } + + public File getRepositoryDir() { + return dir; + } + + private static Closeable asCloseable(final FileStore fs) { + return new Closeable() { + @Override + public void close() throws IOException { + fs.close(); + } + }; + } + + @Override + public String toString() { + return String.format("SegmentNodeStore[%s]", dir); + } + + private static class ExternalBlobFound extends RuntimeException { + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/StoreFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/StoreFactory.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/StoreFactory.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/StoreFactory.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,70 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.node; + +import java.io.IOException; + +import javax.jcr.RepositoryException; + +import org.apache.jackrabbit.core.RepositoryContext; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; +import org.apache.jackrabbit.oak.spi.state.NodeStore; + +import com.google.common.io.Closer; + +public class StoreFactory { + + private final Jackrabbit2Factory jcr2Factory; + + private final NodeStoreFactory nodeStoreFactory; + + public StoreFactory(Jackrabbit2Factory crx2Factory) { + this.jcr2Factory = crx2Factory; + this.nodeStoreFactory = null; + } + + public StoreFactory(NodeStoreFactory nodeStoreFactory) { + this.jcr2Factory = null; + this.nodeStoreFactory = nodeStoreFactory; + } + + public RepositoryContext create(Closer closer) throws IOException, RepositoryException { + if (jcr2Factory == null) { + throw new UnsupportedOperationException(); + } + return jcr2Factory.create(closer); + } + + public NodeStore create(BlobStore blobStore, Closer closer) throws IOException { + if (nodeStoreFactory == null) { + throw new UnsupportedOperationException(); + } + return nodeStoreFactory.create(blobStore, closer); + } + + public boolean isJcr2() { + return jcr2Factory != null; + } + + public boolean hasExternalBlobReferences() throws IOException { + if (isJcr2()) { + return true; + } else { + return nodeStoreFactory.hasExternalBlobReferences(); + } + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/node/TarNodeStore.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,48 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.node; + +import org.apache.jackrabbit.oak.spi.state.NodeState; +import org.apache.jackrabbit.oak.spi.state.NodeStore; +import org.apache.jackrabbit.oak.spi.state.ProxyNodeStore; + +public class TarNodeStore extends ProxyNodeStore { + + private final NodeStore ns; + + private final SuperRootProvider superRootProvider; + + public TarNodeStore(NodeStore ns, SuperRootProvider superRootProvider) { + this.ns = ns; + this.superRootProvider = superRootProvider; + } + + public NodeState getSuperRoot() { + return superRootProvider.getSuperRoot(); + } + + @Override + protected NodeStore getNodeStore() { + return ns; + } + + public interface SuperRootProvider { + + NodeState getSuperRoot(); + + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/CliArgumentException.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/CliArgumentException.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/CliArgumentException.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/CliArgumentException.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,38 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.parser; + +public class CliArgumentException extends Exception { + + private static final long serialVersionUID = -7579563789244874904L; + + private final int exitCode; + + public CliArgumentException(int exitCode) { + super(); + this.exitCode = exitCode; + } + + public CliArgumentException(String message, int exitCode) { + super(message); + this.exitCode = exitCode; + } + + public int getExitCode() { + return exitCode; + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/DatastoreArguments.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/DatastoreArguments.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/DatastoreArguments.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/DatastoreArguments.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,238 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.parser; + +import org.apache.commons.lang.text.StrSubstitutor; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; +import org.apache.jackrabbit.oak.upgrade.cli.blob.BlobStoreFactory; +import org.apache.jackrabbit.oak.upgrade.cli.blob.ConstantBlobStoreFactory; +import org.apache.jackrabbit.oak.upgrade.cli.blob.DummyBlobStoreFactory; +import org.apache.jackrabbit.oak.upgrade.cli.blob.FileBlobStoreFactory; +import org.apache.jackrabbit.oak.upgrade.cli.blob.FileDataStoreFactory; +import org.apache.jackrabbit.oak.upgrade.cli.blob.MissingBlobStoreFactory; +import org.apache.jackrabbit.oak.upgrade.cli.blob.S3DataStoreFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Map; + +import static com.google.common.collect.Maps.newHashMap; +import static org.apache.jackrabbit.oak.upgrade.cli.parser.StoreType.JCR2_DIR_XML; + +/** + * This class parses the input provided by the user and analyses the given node stores + * in order to find out which datastore combination should be used for the migration. + * + * The desired outcome for the combinations of user input can be found in the table below. + * The table is a kind of heuristics that tries to match the user intentions. + * <pre> + * For sidegrade: + || src blobstore defined || src blobs embedded || dst blobstore defined || --copy-binaries || outcome src blobstore || outcome action + | - | - | - | - | missing | copy references¹ + | - | - | - | + | missing | (x) not supported + | - | - | + | * | missing | (x) not supported + | - | + | - | * | embedded | copy to embedded + | - | + | + | * | embedded | copy to defined blobstore + | + | * | - | - | as in src | copy references + | + | * | - | + | as in src | copy to embedded + | + | * | + | * | as in src | copy to defined blobstore + + ¹ - (x) not supported for SegmentMK -> MongoMK migration + + For upgrade: + + || dst blobstore defined || --copy-binaries || outcome src blobstore || outcome action + | - | - | defined by JCR2 | copy references + | - | + | defined by JCR2 | copy to embedded + | + | * | defined by JCR2 | copy to defined blobstore + * </pre> + */ +public class DatastoreArguments { + + private static final Logger log = LoggerFactory.getLogger(DatastoreArguments.class); + + private final BlobStoreFactory definedSrcBlob; + + private final BlobStoreFactory definedDstBlob; + + private final StoreArguments storeArguments; + + private final BlobMigrationCase blobMigrationCase; + + private final MigrationOptions options; + + private final boolean srcEmbedded; + + public DatastoreArguments(MigrationOptions options, StoreArguments storeArguments, boolean srcEmbedded) throws CliArgumentException { + this.storeArguments = storeArguments; + this.options = options; + this.srcEmbedded = srcEmbedded; + + try { + blobMigrationCase = discoverBlobMigrationCase(); + } catch (IOException e) { + log.error("Can't figure out the right blob migration path", e); + throw new CliArgumentException(1); + } + + if (blobMigrationCase == BlobMigrationCase.UNSUPPORTED) { + throw new CliArgumentException("This combination of data- and node-stores is not supported", 1); + } + + try { + definedSrcBlob = options.isSrcBlobStoreDefined() ? getDefinedSrcBlobStore() : null; + definedDstBlob = options.isDstBlobStoreDefined() ? getDefinedDstBlobStore() : null; + } catch(IOException e) { + log.error("Can't read the blob configuration", e); + throw new CliArgumentException(1); + } + + log.info(blobMigrationCase.getDescription(this)); + } + + public BlobStoreFactory getSrcBlobStore() throws IOException { + BlobStoreFactory result; + if (options.isSrcBlobStoreDefined()) { + result = definedSrcBlob; + } else if (blobMigrationCase == BlobMigrationCase.COPY_REFERENCES) { + result = new MissingBlobStoreFactory(); + } else { + result = new DummyBlobStoreFactory(); // embedded + } + log.info("Source blob store: {}", result); + return result; + } + + public BlobStoreFactory getDstBlobStore(BlobStore srcBlobStore) throws IOException { + BlobStoreFactory result; + if (options.isDstBlobStoreDefined()) { + result = definedDstBlob; + } else if (blobMigrationCase == BlobMigrationCase.COPY_REFERENCES && (options.isSrcBlobStoreDefined() || storeArguments.getSrcType() == JCR2_DIR_XML)) { + result = new ConstantBlobStoreFactory(srcBlobStore); + } else if (blobMigrationCase == BlobMigrationCase.COPY_REFERENCES) { + result = new MissingBlobStoreFactory(); + } else { + result = new DummyBlobStoreFactory(); // embedded + } + + log.info("Destination blob store: {}", result); + return result; + } + + private BlobStoreFactory getDefinedSrcBlobStore() throws IOException { + boolean ignoreMissingBinaries = options.isIgnoreMissingBinaries(); + if (options.isSrcFbs()) { + return new FileBlobStoreFactory(options.getSrcFbs()); + } else if (options.isSrcS3()) { + return new S3DataStoreFactory(options.getSrcS3Config(), options.getSrcS3(), ignoreMissingBinaries); + } else if (options.isSrcFds()) { + return new FileDataStoreFactory(options.getSrcFds(), ignoreMissingBinaries); + } else { + return null; + } + } + + private BlobStoreFactory getDefinedDstBlobStore() throws IOException { + if (options.isDstFbs()) { + return new FileBlobStoreFactory(options.getDstFbs()); + } else if (options.isDstS3()) { + return new S3DataStoreFactory(options.getDstS3Config(), options.getDstS3(), false); + } else if (options.isDstFds()) { + return new FileDataStoreFactory(options.getDstFds(), false); + } else { + return null; + } + } + + public enum BlobMigrationCase { + COPY_REFERENCES("Only blob references will be copied"), + EMBEDDED_TO_EMBEDDED("Blobs embedded in ${srcnode} will be embedded in ${dstnode}"), + EMBEDDED_TO_EXTERNAL("Blobs embedded in ${srcnode} will be copied to ${dstblob}"), + EXTERNAL_TO_EMBEDDED("Blobs stored in ${srcblob} will be embedded in ${dstnode}"), + EXTERNAL_TO_EXTERNAL("Blobs stored in ${srcblob} will be copied to ${dstblob}"), + UNSUPPORTED("Unsupported case"); + + private final String description; + + BlobMigrationCase(String description) { + this.description = description; + } + + private String getDescription(DatastoreArguments datastoreArguments) { + Map<String, String> map = newHashMap(); + map.put("srcnode", datastoreArguments.storeArguments.getSrcDescriptor()); + map.put("dstnode", datastoreArguments.storeArguments.getDstDescriptor()); + + if (datastoreArguments.storeArguments.getSrcType() == JCR2_DIR_XML) { + map.put("srcblob", "CRX2 datastore"); + } else { + map.put("srcblob", datastoreArguments.definedSrcBlob == null ? "?" : datastoreArguments.definedSrcBlob.toString()); + } + map.put("dstblob", datastoreArguments.definedDstBlob == null ? "?" : datastoreArguments.definedDstBlob.toString()); + + StrSubstitutor subst = new StrSubstitutor(map); + return subst.replace(description); + } + + } + + public BlobMigrationCase getBlobMigrationCase() { + return blobMigrationCase; + } + + private BlobMigrationCase discoverBlobMigrationCase() throws IOException { + boolean srcDefined = options.isSrcBlobStoreDefined() || storeArguments.getSrcType() == JCR2_DIR_XML; + boolean dstDefined = options.isDstBlobStoreDefined(); + boolean copyBinaries = options.isCopyBinaries(); + + boolean srcSegment = storeArguments.getSrcType().isSegment(); + boolean dstSegment = storeArguments.getDstType().isSegment(); + + // default case, no datastore-related arguments given, but blobs are stored externally + if (!srcDefined && !dstDefined && !srcEmbedded && !copyBinaries) { + if (srcSegment && !dstSegment) { // segment -> document is not supported for this case + return BlobMigrationCase.UNSUPPORTED; + } else { // we try to copy references using MissingBlobStore + return BlobMigrationCase.COPY_REFERENCES; + } + // can't copy binaries if they are stored externally and we don't know where + } else if (!srcDefined && !dstDefined && !srcEmbedded && copyBinaries) { + return BlobMigrationCase.UNSUPPORTED; + // can't copy binaries if they are stored externally and we don't know where + // (even if the destination datastore is defined) + } else if (!srcDefined && !srcEmbedded && dstDefined) { + return BlobMigrationCase.UNSUPPORTED; + // source is embedded and no destination given + } else if (!srcDefined && srcEmbedded && !dstDefined) { + return BlobMigrationCase.EMBEDDED_TO_EMBEDDED; + // source is embedded and the destination is given + } else if (!srcDefined && srcEmbedded && dstDefined) { + return BlobMigrationCase.EMBEDDED_TO_EXTERNAL; + // source is given, no destination, but also no --copy-binaries -> copy references + } else if (srcDefined && !dstDefined && !copyBinaries) { + return BlobMigrationCase.COPY_REFERENCES; + // source is given, no destination, but --copy-binaries -> copy to embedded + } else if (srcDefined && !dstDefined && copyBinaries) { + return BlobMigrationCase.EXTERNAL_TO_EMBEDDED; + // source and destination is given + } else if (srcDefined && dstDefined) { + return BlobMigrationCase.EXTERNAL_TO_EXTERNAL; + } + return BlobMigrationCase.UNSUPPORTED; + } +} Added: jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationCliArguments.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationCliArguments.java?rev=1792993&view=auto ============================================================================== --- jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationCliArguments.java (added) +++ jackrabbit/oak/branches/1.0/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/cli/parser/MigrationCliArguments.java Fri Apr 28 07:16:13 2017 @@ -0,0 +1,67 @@ +/* + * 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.jackrabbit.oak.upgrade.cli.parser; + +import java.util.ArrayList; +import java.util.List; + +import joptsimple.OptionSet; + +public final class MigrationCliArguments { + + private final OptionSet options; + + private final List<String> arguments; + + public MigrationCliArguments(OptionSet options) throws CliArgumentException { + this.options = options; + this.arguments = getNonOptionArguments(); + } + + private List<String> getNonOptionArguments() { + List<String> args = new ArrayList<String>(); + for (Object o : options.nonOptionArguments()) { + args.add(o.toString()); + } + return args; + } + + public boolean hasOption(String optionName) { + return options.has(optionName); + } + + public String getOption(String optionName) { + return (String) options.valueOf(optionName); + } + + public int getIntOption(String optionName) { + return (Integer) options.valueOf(optionName); + } + + public String[] getOptionList(String optionName) { + String option = getOption(optionName); + if (option == null) { + return null; + } else { + return option.split(","); + } + } + + public List<String> getArguments() { + return arguments; + } +}
