You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2013/08/10 07:53:54 UTC
svn commit: r1512568 [36/39] - in /jackrabbit/commons/filevault/trunk: ./
parent/ vault-cli/ vault-cli/src/ vault-cli/src/main/
vault-cli/src/main/appassembler/ vault-cli/src/main/assembly/
vault-cli/src/main/java/ vault-cli/src/main/java/org/ vault-cl...
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltContext.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltContext.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltContext.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,425 @@
+/*
+ * 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.vault.vlt;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Credentials;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.fs.Mounter;
+import org.apache.jackrabbit.vault.fs.api.ImportMode;
+import org.apache.jackrabbit.vault.fs.api.PathFilter;
+import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
+import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
+import org.apache.jackrabbit.vault.fs.api.VaultFileSystem;
+import org.apache.jackrabbit.vault.fs.api.VaultFsConfig;
+import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
+import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.config.ExportRoot;
+import org.apache.jackrabbit.vault.fs.config.MetaInf;
+import org.apache.jackrabbit.vault.util.Constants;
+import org.apache.jackrabbit.vault.util.PathUtil;
+import org.apache.jackrabbit.vault.util.RepositoryProvider;
+import org.apache.jackrabbit.vault.vlt.actions.Action;
+import org.apache.jackrabbit.vault.vlt.meta.Ignored;
+import org.apache.jackrabbit.vault.vlt.meta.MetaDirectory;
+import org.apache.jackrabbit.vault.vlt.meta.xml.zip.ZipMetaDir;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <code>VaultContext</code>...
+ *
+ */
+public class VltContext {
+
+ protected static Logger log = LoggerFactory.getLogger(VltContext.class);
+
+ private final File cwd;
+
+ private final RepositoryProvider repProvider;
+
+ private final CredentialsProvider credsProvider;
+
+ private final ExportRoot exportRoot;
+
+ private Map<RepositoryAddress, VaultFileSystem> fileSystems
+ = new HashMap<RepositoryAddress, VaultFileSystem>();
+
+ private RepositoryAddress mountpoint;
+
+ private boolean verbose;
+
+ private boolean quiet;
+
+ private boolean swallowErrors = true;
+
+ private final PrintStream stdout;
+
+ private String[] defaultFilterRoots = Constants.EMPTY_STRING_ARRAY;
+
+ private String defaultFilter;
+
+ private String fsRoot = "";
+
+ private PathFilter globalIgnored;
+
+ public VltContext(File cwd, File localFile,
+ RepositoryProvider repProvider,
+ CredentialsProvider credsProvider)
+ throws ConfigurationException, IOException {
+ this(cwd, localFile, repProvider, credsProvider, System.out);
+ }
+
+ public VltContext(File cwd, File localFile,
+ RepositoryProvider repProvider,
+ CredentialsProvider credsProvider,
+ PrintStream out)
+ throws ConfigurationException, IOException {
+ if (!cwd.exists()) {
+ throw new FileNotFoundException(cwd.getAbsolutePath());
+ }
+ if (!localFile.exists()) {
+ throw new FileNotFoundException(localFile.getAbsolutePath());
+ }
+ this.stdout = out;
+ this.cwd = cwd;
+ this.repProvider = repProvider;
+ this.credsProvider = credsProvider;
+ ExportRoot er = ExportRoot.findRoot(localFile);
+ if (er == null) {
+ er = new ExportRoot(localFile);
+ }
+ this.exportRoot = er;
+ }
+
+ public RepositoryAddress getMountpoint() throws VltException {
+ if (mountpoint == null) {
+ File dir = new File(exportRoot.getJcrRoot(), VltDirectory.META_DIR_NAME);
+ MetaDirectory rootMeta = VltContext.createMetaDirectory(dir);
+ try {
+ String addr = rootMeta.getRepositoryUrl();
+ if (addr == null) {
+ throw new VltException("Root directory must provide a repository url file.");
+ }
+ mountpoint = new RepositoryAddress(addr);
+ } catch (IOException e) {
+ throw new VltException("error while reading repository address.", e);
+ } catch (URISyntaxException e) {
+ throw new VltException("Illegal repository address.", e);
+ }
+ }
+ return mountpoint;
+ }
+
+ public static MetaDirectory createMetaDirectory(File base) throws VltException {
+ //return new FileMetaDir(base);
+ try {
+ //return new TarMetaDir(base);
+ return new ZipMetaDir(base);
+ } catch (IOException e) {
+ throw new VltException("Error creating meta directory.", e);
+ }
+ }
+
+ public String getFsRoot() {
+ return fsRoot;
+ }
+
+ public void setFsRoot(String fsRoot) {
+ if (fsRoot == null || fsRoot.equals("/")) {
+ this.fsRoot = "";
+ } else {
+ this.fsRoot = fsRoot;
+ }
+ }
+
+ public PathFilter getGlobalIgnored() {
+ return globalIgnored;
+ }
+
+ public void setGlobalIgnored(PathFilter globalIgnored) {
+ this.globalIgnored = globalIgnored;
+ }
+
+ /**
+ * Sets the filesystem root to the aggregate path defined by the entries
+ * of the given directory.
+ *
+ * @param dir the directory
+ * @throws VltException if an error occurs
+ */
+ public void setFsRoot(VltDirectory dir) throws VltException {
+ String aPath = dir.getAggregatePath();
+ if (aPath != null) {
+ RepositoryAddress adr = getMountpoint().resolve(aPath);
+ setFsRoot(aPath);
+ setMountpoint(adr);
+ }
+ }
+
+ public void setMountpoint(RepositoryAddress addr) throws VltException {
+ mountpoint = addr;
+ File dir = new File(exportRoot.getJcrRoot(), VltDirectory.META_DIR_NAME);
+ MetaDirectory rootMeta = VltContext.createMetaDirectory(dir);
+ try {
+ String url = addr.toString();
+ if (fsRoot.length() > 0 && url.endsWith(fsRoot)) {
+ url = url.substring(0, url.length() - fsRoot.length());
+ }
+ rootMeta.setRepositoryUrl(url);
+ } catch (IOException e) {
+ throw new VltException("error while writing repository address.", e);
+ }
+ }
+
+ public Session login(RepositoryAddress mountpoint) throws RepositoryException {
+ Repository rep = repProvider.getRepository(mountpoint);
+ Credentials creds = credsProvider.getCredentials(mountpoint);
+ Session s = rep.login(creds);
+ // hack to store credentials
+ credsProvider.storeCredentials(mountpoint, creds);
+ return s;
+ }
+
+ public VaultFileSystem getFileSystem(RepositoryAddress mountpoint)
+ throws VltException {
+ VaultFileSystem fs = fileSystems.get(mountpoint);
+ if (fs == null) {
+ try {
+ // check if export root already defines config and filter
+ DefaultWorkspaceFilter filter = null;
+ VaultFsConfig config = null;
+ if (exportRoot != null && exportRoot.getMetaInf() != null) {
+ filter = (DefaultWorkspaceFilter) exportRoot.getMetaInf().getFilter();
+ config = exportRoot.getMetaInf().getConfig();
+ }
+ if (filter == null && defaultFilterRoots.length > 0) {
+ filter = new DefaultWorkspaceFilter();
+ for (String root: defaultFilterRoots) {
+ filter.add(new PathFilterSet(root));
+ }
+ stdout.printf("Created default filter:%n%s", filter.getSourceAsString());
+ }
+ if (filter == null && defaultFilter != null) {
+ filter = new DefaultWorkspaceFilter();
+ try {
+ filter.load(new File(defaultFilter));
+ } catch (ConfigurationException e) {
+ throw new VltException("Specified filter is not valid.", e);
+ }
+ }
+ // get .vltignore files
+ if (exportRoot != null && filter != null) {
+ if (globalIgnored == null) {
+ globalIgnored = new Ignored(this, cwd);
+ }
+ filter.setGlobalIgnored(globalIgnored);
+ }
+ // override any import mode defined in the filter as this is not expected when committing files (GRANITE-XYZ)
+ if (filter != null) {
+ filter.setImportMode(ImportMode.REPLACE);
+ }
+
+ Repository rep = repProvider.getRepository(mountpoint);
+ Credentials creds = credsProvider.getCredentials(mountpoint);
+ fs = Mounter.mount(config, filter, rep, creds, mountpoint, fsRoot);
+ // hack to store credentials
+ credsProvider.storeCredentials(mountpoint, creds);
+
+ } catch (RepositoryException e) {
+ throw new VltException("Unable to mount filesystem", e);
+ } catch (IOException e) {
+ throw new VltException("Unable to mount filesystem", e);
+ }
+ fileSystems.put(mountpoint, fs);
+ }
+ return fs;
+ }
+
+ public ExportRoot getExportRoot() {
+ return exportRoot;
+ }
+
+ public MetaInf getMetaInf() {
+ return exportRoot.isValid() ? exportRoot.getMetaInf() : null;
+ }
+
+ public String[] getDefaultFilterRoots() {
+ return defaultFilterRoots;
+ }
+
+ public void setDefaultFilterRoots(String[] defaultFilterRoots) {
+ this.defaultFilterRoots = defaultFilterRoots;
+ }
+
+ public String getDefaultFilter() {
+ return defaultFilter;
+ }
+
+ public void setDefaultFilter(String defaultFilter) {
+ this.defaultFilter = defaultFilter;
+ }
+
+ public void close() {
+ for (RepositoryAddress addr: fileSystems.keySet()) {
+ VaultFileSystem fs = fileSystems.get(addr);
+ try {
+ fs.unmount();
+ } catch (RepositoryException e) {
+ log.warn("Error while unmounting fs.", e);
+ }
+ }
+ fileSystems.clear();
+ }
+
+ public boolean execute(Action action) throws VltException {
+ try {
+ action.run(this);
+ } catch (VltException e) {
+ if (swallowErrors && e.isUserError()) {
+ printError(e);
+ return false;
+ } else {
+ throw e;
+ }
+ }
+ return true;
+ }
+
+ public String getCwdRelativePath(String path) {
+ return PathUtil.getRelativeFilePath(cwd.getPath(), path);
+ }
+
+ public VltException error(String path, String msg) {
+ path = getCwdRelativePath(path);
+ return new VltException(path, true, msg, null);
+ }
+
+ public VltException exception(String path, String msg, Throwable cause) {
+ path = getCwdRelativePath(path);
+ return new VltException(path, false, msg, cause);
+ }
+
+ public void printAction(VltFile file, FileAction action) {
+ printAction(file.getPath(), action, file.getContentType());
+ }
+
+ public void printAction(String path, FileAction action, String contentType) {
+ if (!quiet && (verbose || action != FileAction.VOID)) {
+ path = getCwdRelativePath(path);
+ if (action == FileAction.ADDED && contentType != null) {
+ stdout.printf("%s %s (%s)%n", action.letter, path, contentType);
+ } else {
+ stdout.printf("%s %s%n", action.letter, path);
+ }
+ stdout.flush();
+ }
+ }
+
+ public void printError(VltException e) {
+ stdout.println(e.getMessage());
+ stdout.flush();
+ }
+
+ public void printMessage(VltFile file, String msg) {
+ if (!quiet) {
+ String path = getCwdRelativePath(file.getPath());
+ stdout.printf("%s %s%n", path, msg);
+ stdout.flush();
+ }
+ }
+
+ public void printMessage(String msg, VltFile file) {
+ if (!quiet) {
+ String path = getCwdRelativePath(file.getPath());
+ stdout.printf("%s %s%n", msg, path);
+ stdout.flush();
+ }
+ }
+
+ public void printMessage(String msg) {
+ if (!quiet) {
+ stdout.println(msg);
+ stdout.flush();
+ }
+ }
+
+ public void printStatus(VltFile file)
+ throws VltException {
+ String path = getCwdRelativePath(file.getPath());
+ VltFile.State state = file.getStatus();
+ if (quiet && state == VltFile.State.UNKNOWN) {
+ return;
+ }
+ if (verbose || state != VltFile.State.CLEAN) {
+ if (state == VltFile.State.ADDED && file.getContentType() != null) {
+ stdout.printf("%s %s (%s)%n", state.letter, path, file.getContentType());
+ } else {
+ stdout.printf("%s %s%n", state.letter, path);
+ }
+ stdout.flush();
+ }
+ }
+
+ public void printRemoteStatus(VltFile file, FileAction action)
+ throws VltException {
+ String path = getCwdRelativePath(file.getPath());
+ VltFile.State state = file.getStatus();
+ if (quiet && state == VltFile.State.UNKNOWN && action == FileAction.VOID) {
+ return;
+ }
+ if (verbose || state != VltFile.State.CLEAN || action != FileAction.VOID) {
+ stdout.printf("%s%s %s%n", state.letter, action.letter, path);
+ stdout.flush();
+ }
+ }
+
+ public PrintStream getStdout() {
+ return stdout;
+ }
+
+ public File getCwd() {
+ return cwd;
+ }
+
+ public boolean isVerbose() {
+ return verbose;
+ }
+
+ public void setVerbose(boolean verbose) {
+ this.verbose = verbose;
+ }
+
+ public boolean isQuiet() {
+ return quiet;
+ }
+
+ public void setQuiet(boolean quiet) {
+ this.quiet = quiet;
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltDirectory.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltDirectory.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltDirectory.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltDirectory.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,490 @@
+/*
+ * 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.vault.vlt;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.vault.fs.api.VaultFile;
+import org.apache.jackrabbit.vault.fs.api.VaultFileOutput;
+import org.apache.jackrabbit.vault.fs.api.VaultFileSystem;
+import org.apache.jackrabbit.vault.fs.api.VaultFsTransaction;
+import org.apache.jackrabbit.vault.util.Constants;
+import org.apache.jackrabbit.vault.util.FileInputSource;
+import org.apache.jackrabbit.vault.util.LineOutputStream;
+import org.apache.jackrabbit.vault.vlt.actions.Action;
+import org.apache.jackrabbit.vault.vlt.meta.MetaDirectory;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntries;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntry;
+
+/**
+ * <code>VltDirectory</code>...
+ *
+ */
+public class VltDirectory {
+
+ public static final String META_DIR_NAME = ".vlt";
+
+ private final VltContext ctx;
+
+ private File dir;
+
+ private MetaDirectory metaDir;
+
+ //private final File entriesFile;
+
+ private VltEntries entries;
+
+ private FileList files;
+
+ public VltDirectory(VltContext ctx, File directory) throws VltException {
+ this.ctx = ctx;
+ this.dir = directory;
+ if (!dir.exists()) {
+ throw ctx.error(dir.getPath(), "no such file or directory.");
+ }
+ if (!dir.isDirectory()) {
+ throw ctx.error(dir.getPath(), "not a directory.");
+ }
+ if (dir.getName().equals(META_DIR_NAME)) {
+ throw ctx.error(dir.getPath(), "meta directory not controllable.");
+ }
+ metaDir = VltContext.createMetaDirectory(new File(dir, META_DIR_NAME));
+ //entriesFile = new File(metaDir, ENTRIES_FILE_NAME);
+
+ init();
+ }
+
+ public VltDirectory getParent() throws VltException {
+ return new VltDirectory(ctx, dir.getParentFile());
+ }
+
+ public String getAggregatePath() throws VltException {
+ VltDirectory parent = getParent();
+ VltEntries es = parent.getEntries();
+ if (es != null) {
+ VltEntry e = es.getEntry(dir.getName());
+ if (e != null) {
+ return e.getAggregatePath();
+ }
+ } else {
+ // fallback if the parent is not controllable. check the
+ // aggregate path of the .content.xml
+ VltEntry e = entries == null ? null : entries.getEntry(Constants.DOT_CONTENT_XML);
+ if (e != null) {
+ return e.getAggregatePath();
+ }
+ }
+ return null;
+ }
+
+ public VltContext getContext() {
+ return ctx;
+ }
+
+ public boolean isControlled() {
+ return entries != null;
+ }
+
+ public void assertControlled() throws VltException {
+ if (entries == null) {
+ throw ctx.exception(dir.getPath(), "Directory is not under vault control.", null);
+ }
+ }
+
+ private void init() throws VltException {
+ entries = metaDir.getEntries();
+ if (entries != null) {
+ files = new FileList(this, entries);
+ }
+ }
+
+ public void close() {
+ if (dir != null) {
+ dir = null;
+ }
+ if (metaDir != null) {
+ try {
+ metaDir.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ metaDir = null;
+ }
+ }
+
+ public void control(String path, String aPath) throws VltException {
+ if (!metaDir.exists()) {
+ try {
+ metaDir.create(path);
+ } catch (IOException e) {
+ throw ctx.exception(path, "Error while creating.", e);
+ }
+ }
+ entries = metaDir.getEntries();
+ if (entries == null) {
+ throw ctx.error(metaDir.getFile().getPath(), "No entries found.");
+ }
+ try {
+ metaDir.sync();
+ } catch (IOException e) {
+ throw ctx.exception(path, "Error while saving.", e);
+ }
+ files = new FileList(this, entries);
+ }
+
+ public void uncontrol()
+ throws VltException {
+ if (metaDir.exists()) {
+ try {
+ metaDir.delete();
+ } catch (IOException e) {
+ throw ctx.exception(getPath(), "Error while deleting meta directory", e);
+ }
+ }
+ entries = null;
+ files = null;
+ }
+
+ public MetaDirectory getMetaDirectory() {
+ return metaDir;
+ }
+
+ public File getDirectory() {
+ return dir;
+ }
+
+ public String getPath() {
+ return dir.getPath();
+ }
+
+ public VltEntries getEntries() {
+ return entries;
+ }
+
+ public VaultFile getRemoteDirectory(VltContext ctx) throws VltException {
+ assertControlled();
+ try {
+ VaultFileSystem fs = ctx.getFileSystem(ctx.getMountpoint());
+ return fs.getFile(entries.getPath());
+ } catch (IOException e) {
+ throw new VltException("Unable to get remote directory.", e);
+ } catch (RepositoryException e) {
+ throw new VltException("Unable to get remote directory.", e);
+ }
+ }
+
+ public void prepareCommit(VaultFsTransaction tx, Collection<String> names,
+ boolean nonRecursive, boolean force)
+ throws VltException {
+ assertControlled();
+ VaultFile remoteDir = getRemoteDirectory(ctx);
+ if (remoteDir == null) {
+ throw ctx.error(getPath(), "Remote directory does not exist.");
+ }
+ if (names.isEmpty()) {
+ // add all files in this directory
+ for (VltFile file : getFiles()) {
+ prepareCommit(tx, remoteDir, file, nonRecursive, force);
+ }
+ } else {
+ for (String name: names) {
+ VltFile file = files.getFile(name);
+ if (file == null) {
+ throw ctx.error(name, "no such file or directory.");
+ }
+ prepareCommit(tx, remoteDir, file, nonRecursive, force);
+ }
+ }
+ saveEntries();
+ }
+
+ public void updateComitted(String path, String fileName) throws VltException {
+ assertControlled();
+ VltFile file = files().getFile(fileName);
+ VaultFile remote;
+ try {
+ VaultFile rd = getRemoteDirectory(ctx);
+ remote = rd == null ? null : rd.getChild(fileName);
+ } catch (RepositoryException e) {
+ throw ctx.exception(dir.getPath(), "Error while retrieving remote directory.", e);
+ }
+ if (file == null && remote == null) {
+ // removed and file gone
+ ctx.printAction(getPath() + Constants.FS_NATIVE + fileName, FileAction.DELETED, null);
+ } else if (file == null) {
+ // added
+ update(remote, fileName);
+ } else {
+ FileAction a = file.commit(remote);
+ if (a != FileAction.VOID) {
+ entries.update(file);
+ saveEntries();
+ ctx.printAction(file, a);
+ }
+ }
+ }
+
+ private void update(VaultFile remote, String name)
+ throws VltException {
+ VltFile file = new VltFile(this, name, null);
+ files.addFile(file);
+
+ FileAction action = file.update(remote, false);
+
+ // write back entries
+ entries.update(file);
+ saveEntries();
+ ctx.printAction(file, action);
+ sync();
+ }
+
+ private void prepareCommit(VaultFsTransaction tx, VaultFile remoteDir,
+ VltFile file, boolean nonRecursive, boolean force)
+ throws VltException {
+ VaultFile remoteFile;
+ try {
+ remoteFile = remoteDir == null
+ ? null
+ : remoteDir.getChild(file.getName());
+ } catch (RepositoryException e) {
+ throw ctx.exception(file.getPath(), "Error while retrieving status", e);
+ }
+
+ if (file.status(remoteFile) != FileAction.VOID && !force) {
+ throw ctx.error(file.getPath(), "Some files need to be updated first." +
+ " Specify --force to overwrite remote files.");
+ }
+ try {
+ switch (file.getStatus()) {
+ case MODIFIED:
+ FileInputSource fis = new FileInputSource(file.getFile());
+ if (file.isBinary()) {
+ fis.setLineSeparator(LineOutputStream.LS_BINARY);
+ }
+ tx.modify(remoteFile, fis);
+ ctx.printMessage("sending....", file);
+ break;
+ case DELETED:
+ tx.delete(remoteFile);
+ ctx.printMessage("deleting...", file);
+ break;
+ case ADDED:
+ String path = this.getEntries().getPath();
+ if (path.endsWith("/")) {
+ path += file.getName();
+ } else {
+ path += "/" + file.getName();
+ }
+ if (file.canDescend()) {
+ tx.mkdir(path);
+ } else {
+ fis = new FileInputSource(file.getFile());
+ if (file.isBinary()) {
+ fis.setLineSeparator(LineOutputStream.LS_BINARY);
+ }
+ VaultFileOutput out = tx.add(path, fis);
+ // set the content type hint
+ out.setContentType(file.getContentType());
+ }
+ ctx.printMessage("adding.....", file);
+ break;
+ default:
+ // ignore
+ }
+ } catch (IOException e) {
+ ctx.exception(file.getPath(), "Error while preparing commit.", e);
+ } catch (RepositoryException e) {
+ ctx.exception(file.getPath(), "Error while preparing commit.", e);
+ }
+
+ if (file.canDescend() && !nonRecursive) {
+ VltDirectory dir = file.descend();
+ if (dir.isControlled()) {
+ // add all files in this directory
+ VaultFile remDir = dir.getRemoteDirectory(ctx);
+ for (VltFile child: dir.getFiles()) {
+ dir.prepareCommit(tx, remDir, child, nonRecursive, force);
+ }
+ dir.saveEntries();
+ }
+ dir.close();
+ }
+ }
+
+ public Collection<VltFile> getFiles() {
+ if (files == null) {
+ return Collections.emptySet();
+ } else {
+ return files.getFiles();
+ }
+ }
+
+ public void apply(Action action, String name, boolean nonRecursive)
+ throws VltException {
+ apply(action, Arrays.asList(name), nonRecursive);
+ }
+
+ public void apply(Action action, Collection<String> names,
+ boolean nonRecursive) throws VltException {
+ if (!action.run(this, null)) {
+ return;
+ }
+ if (names.isEmpty()) {
+ // add all files in this directory
+ for (VltFile file : getFiles()) {
+ apply(action, file, nonRecursive);
+ }
+ } else {
+ for (String name: names) {
+ // special check for jcr_root
+ VltFile file;
+ if (ctx.getExportRoot().getJcrRoot().getParentFile().equals(dir)) {
+ file = new VltFile(this, name, null);
+ } else {
+ assertControlled();
+ file = files.getFile(name);
+ }
+ if (file == null) {
+ throw ctx.error(name, "no such file or directory.");
+ }
+ apply(action, file, nonRecursive);
+ }
+ }
+ }
+
+ private void apply(Action action, VltFile file, boolean nonRecursive)
+ throws VltException {
+ action.run(this, file, null);
+ if (entries != null) {
+ entries.update(file);
+ sync();
+ }
+ if (file.canDescend() && !nonRecursive) {
+ VltDirectory dir = file.descend();
+ dir.apply(action, Collections.<String>emptyList(), nonRecursive);
+ dir.close();
+ }
+ }
+
+
+ public void sync() throws VltException {
+ saveEntries();
+ // reload files (todo: make better)
+ files = new FileList(this, entries);
+ }
+
+ public void applyWithRemote(Action action, Collection<String> names, boolean nonRecursive)
+ throws VltException {
+ applyWithRemote(action, getRemoteDirectory(ctx), names, nonRecursive);
+ }
+
+ public void applyWithRemote(Action action, String name, boolean nonRecursive)
+ throws VltException {
+ applyWithRemote(action, getRemoteDirectory(ctx), Arrays.asList(name), nonRecursive);
+ }
+
+ public void applyWithRemote(Action action, VaultFile remoteDir, Collection<String> names,
+ boolean nonRecursive)
+ throws VltException {
+ if (!action.run(this, remoteDir)) {
+ return;
+ }
+ if (names.isEmpty()) {
+ // get the status of remote files
+ Set<String> processed = new HashSet<String>();
+ if (remoteDir != null && files != null) {
+ Collection<? extends VaultFile> remoteFiles;
+ try {
+ remoteFiles = remoteDir.getChildren();
+ } catch (RepositoryException e) {
+ throw new VltException("Error while retrieving file.", e);
+ }
+ for (VaultFile remoteFile : remoteFiles) {
+ String name = remoteFile.getName();
+ processed.add(name);
+ applyWithRemote(action, files.getFile(name), remoteFile, nonRecursive);
+ }
+ }
+ // second go over all local ones
+ for (VltFile file: getFiles()) {
+ if (!processed.contains(file.getName())) {
+ applyWithRemote(action, file, null, nonRecursive);
+ }
+ }
+ } else {
+ try {
+ for (String name: names) {
+ VltFile file = files.getFile(name);
+ VaultFile remoteFile = remoteDir.getChild(name);
+ applyWithRemote(action, file, remoteFile, nonRecursive);
+ }
+ } catch (RepositoryException e) {
+ throw new VltException("Error while retrieving file.", e);
+ }
+ }
+ }
+
+ public void applyWithRemote(Action action, VltFile file, VaultFile remoteFile,
+ boolean nonRecursive)
+ throws VltException {
+ // if remote file is missing, do depth first
+ if (remoteFile == null && file != null && file.canDescend() && !nonRecursive) {
+ VltDirectory dir = file.descend();
+ dir.applyWithRemote(action, remoteFile, Collections.<String>emptyList(), nonRecursive);
+ dir.close();
+ }
+
+ // run on 'this' file
+ action.run(this, file, remoteFile);
+ saveEntries();
+
+ if (remoteFile != null) {
+ // refetch file
+ if (file == null) {
+ file = files.getFile(remoteFile.getName());
+ }
+
+ // check again deep
+ if (file != null && file.canDescend() && !nonRecursive) {
+ VltDirectory dir = file.descend();
+ dir.applyWithRemote(action, remoteFile, Collections.<String>emptyList(), nonRecursive);
+ dir.close();
+ }
+ }
+ }
+
+ private void saveEntries() throws VltException {
+ try {
+ metaDir.sync();
+ } catch (IOException e) {
+ throw ctx.error(getPath(), "Error while saving entries: " + e);
+ }
+ }
+
+ public FileList files() throws VltException {
+ assertControlled();
+ return files;
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltException.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltException.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltException.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltException.java Sat Aug 10 05:53:42 2013
@@ -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.vault.vlt;
+
+/**
+ * <code>VaultException</code>...
+ *
+ */
+public class VltException extends Exception {
+
+ static final long serialVersionUID = -4355975803798981445L;
+
+ private final String path;
+
+ private final boolean isUserError;
+
+ public VltException(String message) {
+ this(null, false, message, null);
+ }
+
+ public VltException(String path, String message) {
+ this(path, false, message, null);
+ }
+
+ public VltException(String message, Throwable cause) {
+ this(null, false, message, cause);
+ }
+
+ public VltException(String path, String message, Throwable cause) {
+ this(path, false, message, cause);
+ }
+
+ public VltException(String path, boolean isUserError, String message, Throwable cause) {
+ super(message, cause);
+ this.path = path;
+ this.isUserError = isUserError;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public boolean isUserError() {
+ return isUserError;
+ }
+
+ public String message() {
+ return super.getMessage();
+ }
+
+ public String getMessage() {
+ return path == null || path.equals("") || path.equals(".")
+ ? super.getMessage()
+ : path + ": " + super.getMessage();
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltFile.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltFile.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltFile.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltFile.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,1025 @@
+/*
+ * 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.vault.vlt;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.vault.fs.VaultFileCopy;
+import org.apache.jackrabbit.vault.fs.api.VaultFile;
+import org.apache.jackrabbit.vault.util.Constants;
+import org.apache.jackrabbit.vault.util.LineOutputStream;
+import org.apache.jackrabbit.vault.util.MD5;
+import org.apache.jackrabbit.vault.util.MimeTypes;
+import org.apache.jackrabbit.vault.util.PathUtil;
+import org.apache.jackrabbit.vault.util.diff.DiffWriter;
+import org.apache.jackrabbit.vault.util.diff.Document;
+import org.apache.jackrabbit.vault.util.diff.DocumentDiff;
+import org.apache.jackrabbit.vault.util.diff.DocumentDiff3;
+import org.apache.jackrabbit.vault.util.diff.DocumentSource;
+import org.apache.jackrabbit.vault.util.diff.FileDocumentSource;
+import org.apache.jackrabbit.vault.util.diff.Hunk3;
+import org.apache.jackrabbit.vault.util.diff.LineElementsFactory;
+import org.apache.jackrabbit.vault.vlt.meta.MetaFile;
+import org.apache.jackrabbit.vault.vlt.meta.MetaFileDocSource;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntry;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntryInfo;
+
+/**
+ * <code>VltFile</code>...
+ *
+ */
+public class VltFile implements DocumentSource {
+
+ public static final String PROP_CONTENT_TYPE = "vlt:mime-type";
+
+ /**
+ * Possible state of this file
+ */
+ public enum State {
+ CLEAN (" "),
+ ADDED ("A"),
+ CONFLICTED ("C"),
+ DELETED ("D"),
+ IGNORED ("I"),
+ MODIFIED ("M"),
+ REPLACED ("R"),
+ UNKNOWN("?"),
+ MISSING ("!"),
+ OBSTRUCTED ("~"),
+ VOID (" ");
+
+ public final String letter;
+
+ private State(String letter) {
+ this.letter = letter;
+ }
+
+ public String toString() {
+ return name().toLowerCase() + " (" + letter + ")";
+ }
+ }
+
+ private final VltDirectory parent;
+
+ private final File file;
+
+ private final String name;
+
+ private VltEntry entry;
+
+ public VltFile(VltDirectory parent, String name, VltEntry entry)
+ throws VltException {
+ this.parent = parent;
+ this.name = name;
+ this.entry = entry;
+ this.file = new File(parent.getDirectory(), name);
+ }
+
+ public Properties getProperties() throws VltException {
+ Properties props = new Properties();
+ if (entry != null) {
+ VltEntryInfo info = entry.work();
+ String ct = info.getContentType();
+ if (ct != null) {
+ props.put(PROP_CONTENT_TYPE, ct);
+ }
+ }
+ return props;
+ }
+
+ public String getProperty(String name) throws VltException {
+ if (entry != null) {
+ VltEntryInfo info = entry.work();
+ if (name.equals(PROP_CONTENT_TYPE)) {
+ return info.getContentType();
+ }
+ }
+ return null;
+ }
+
+ public void setProperty(String name, String value) throws VltException {
+ if (entry == null) {
+ throw error("Can't set property to non controlled file.");
+ }
+ VltEntryInfo info = entry.work();
+ if (info == null) {
+ throw error("Can't set property to non controlled file.");
+ }
+ if (name.equals(PROP_CONTENT_TYPE)) {
+ if (!file.isDirectory()) {
+ // silently ignore directories
+ info.setContentType(value);
+ parent.getContext().printMessage(this, name + "=" + value);
+ }
+ } else {
+ throw error("Generic properies not supported, yet");
+ }
+ }
+
+ public State getStatus() throws VltException {
+ State state = State.VOID;
+ if (entry == null) {
+ if (file.exists()) {
+ // special check for jcr_root
+ if (file.equals(parent.getContext().getExportRoot().getJcrRoot())) {
+ state = State.CLEAN;
+ } else {
+ state = State.UNKNOWN;
+ }
+ } else {
+ state = State.VOID;
+ }
+ } else {
+ switch (entry.getState()) {
+ case CLEAN:
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ VltDirectory dir = descend();
+ if (dir.isControlled()) {
+ state = State.CLEAN;
+ } else {
+ state = State.OBSTRUCTED;
+ }
+ } else {
+ VltEntryInfo work = entry.work();
+ VltEntryInfo base = entry.base();
+ assert work != null;
+ assert base != null;
+
+ try {
+ work.update(file, false);
+ } catch (IOException e) {
+ throw exception("Error while calculating status.", e);
+ }
+ state = work.isSame(base) ? State.CLEAN : State.MODIFIED;
+ }
+ } else {
+ state = State.MISSING;
+ }
+ break;
+ case ADDED:
+ if (file.exists()) {
+ state = State.ADDED;
+ } else {
+ state = State.MISSING;
+ }
+ break;
+ case CONFLICT:
+ state = State.CONFLICTED;
+ break;
+ case DELETED:
+ state = State.DELETED;
+ break;
+ }
+ }
+ return state;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ public String getPath() {
+ return file.getPath();
+ }
+
+ public MetaFile getBaseFile(boolean create) throws VltException {
+ try {
+ return parent.getMetaDirectory().getBaseFile(name, create);
+ } catch (IOException e) {
+ throw new VltException(getPath(), "Error opening base file.", e);
+ }
+ }
+
+ public String getContentType() {
+ if (entry != null && !file.isDirectory()) {
+ VltEntryInfo work = entry.work();
+ if (work != null) {
+ return work.getContentType();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Checks if this file has binary content. It does not actually read the
+ * file data but calls {@link MimeTypes#isBinary(String)} with the content
+ * type of the work file.
+ * @return <code>true</code> if this is binary
+ */
+ public boolean isBinary() {
+ return MimeTypes.isBinary(getContentType());
+ }
+
+
+ public MetaFile getTmpFile() throws VltException {
+ try {
+ return parent.getMetaDirectory().getTmpFile(name, true);
+ } catch (IOException e) {
+ throw new VltException(getPath(), "Error opening tmp file.", e);
+ }
+ }
+
+ public boolean canDescend() {
+ return file.isDirectory();
+ }
+
+ public VltDirectory descend() throws VltException {
+ if (!canDescend()) {
+ throw new VltException("Cannot descend into non directory.");
+ }
+ return new VltDirectory(parent.getContext(), file);
+ }
+
+ public VltEntry getEntry() {
+ return entry;
+ }
+
+ public void diff() throws VltException {
+ State state = getStatus();
+ if (entry == null || entry.isDirectory()) {
+ return;
+ }
+ VltEntryInfo work = entry.work();
+ VltEntryInfo base = entry.base();
+ if (work == null || base == null) {
+ return;
+ }
+ switch (state) {
+ case ADDED:
+ case CONFLICTED:
+ case DELETED:
+ case MODIFIED:
+ break;
+ case IGNORED:
+ case MISSING:
+ case OBSTRUCTED:
+ case REPLACED:
+ case UNKNOWN:
+ case VOID:
+ case CLEAN:
+ return;
+ }
+ if (MimeTypes.isBinary(work.getContentType()) || MimeTypes.isBinary(base.getContentType())) {
+ PrintStream s = parent.getContext().getStdout();
+ s.printf("Index: %s%n", getName());
+ s.println("===================================================================");
+ s.println("Cannot display: file marked as binary type.");
+ s.printf("vlt:mime-type = %s%n", work.getContentType());
+ s.flush();
+ return;
+ }
+ try {
+ // do the actual diff
+ PrintStream s = parent.getContext().getStdout();
+ DiffWriter out = new DiffWriter(new OutputStreamWriter(s, Constants.ENCODING));
+ out.write("Index: ");
+ out.write(getName());
+ out.writeNewLine();
+ out.write("===================================================================");
+ out.writeNewLine();
+
+ Reader r0 = getBaseFile(false) == null ? null : getBaseFile(false).getReader();
+ Document d0 = new Document(this, LineElementsFactory.create(this, r0, false));
+ Reader r1 = file.exists() ? new InputStreamReader(FileUtils.openInputStream(file), Constants.ENCODING) : null;
+ Document d1 = new Document(this, LineElementsFactory.create(this, r1, false));
+
+ DocumentDiff diff;
+ try {
+ diff = d0.diff(d1);
+ } finally {
+ IOUtils.closeQuietly(r0);
+ IOUtils.closeQuietly(r1);
+ }
+ diff.write(out, 3);
+ out.flush();
+ } catch (IOException e) {
+ throw exception("Error while writing diff.", e);
+ }
+
+ }
+
+ public FileAction delete(boolean force) throws VltException {
+ State state = getStatus();
+ switch (state) {
+ case ADDED:
+ case CONFLICTED:
+ case MODIFIED:
+ case REPLACED:
+ if (!force) {
+ parent.getContext().printMessage(this, "has local modification. use --force to delete anyway");
+ return FileAction.VOID;
+ }
+ break;
+ case CLEAN:
+ case MISSING:
+ case DELETED:
+ break;
+ case IGNORED:
+ case OBSTRUCTED:
+ case UNKNOWN:
+ case VOID:
+ if (!force) {
+ parent.getContext().printMessage(this, "is not under version control. use --force to delete anyway");
+ return FileAction.VOID;
+ }
+ break;
+ }
+ if (entry != null && entry.delete(file)) {
+ entry = null;
+ }
+ return FileAction.DELETED;
+ }
+
+ public FileAction commit(VaultFile remoteFile) throws VltException {
+ if (remoteFile == null) {
+ return doDelete(false);
+ } else {
+ return doUpdate(remoteFile, false);
+ }
+ }
+
+ public boolean revert() throws VltException {
+ State state = getStatus();
+ switch (state) {
+ case ADDED:
+ doDelete(true);
+ entry = null;
+ return true;
+
+ case CONFLICTED:
+ resolved(true);
+ // no break;
+ case DELETED:
+ case MISSING:
+ case MODIFIED:
+ doRevert();
+ return true;
+
+ case IGNORED:
+ case CLEAN:
+ case OBSTRUCTED:
+ case REPLACED:
+ case UNKNOWN:
+ case VOID:
+ default:
+ return false;
+ }
+ }
+
+ public boolean resolved(boolean force) throws VltException {
+ if (getStatus() != State.CONFLICTED) {
+ return false;
+ }
+ if (!force) {
+ // check if the file still contains the diff markers
+ boolean mayContainMarker = false;
+ try {
+ BufferedReader in = new BufferedReader(new FileReader(file));
+ String line;
+ while ((line = in.readLine()) != null) {
+ if (line.startsWith(Hunk3.MARKER_B[0])
+ || line.startsWith(Hunk3.MARKER_L[0])
+ || line.startsWith(Hunk3.MARKER_R[0])
+ || line.startsWith(Hunk3.MARKER_M[0])) {
+ mayContainMarker = true;
+ break;
+ }
+ }
+ } catch (IOException e) {
+ throw exception("Error while reading file.", e);
+ }
+ if (mayContainMarker) {
+ throw error("File still contains conflict markers. use --force to force resolve.");
+ }
+ }
+
+ // resolve entry
+ try {
+ entry.resolved(getTmpFile(), file, getBaseFile(false));
+ } catch (IOException e) {
+ throw exception("Error while copying files.", e);
+ }
+
+ return true;
+ }
+
+ public FileAction update(VaultFile remoteFile, boolean force)
+ throws VltException {
+ State state = getStatus();
+ switch (state) {
+ case IGNORED:
+ case OBSTRUCTED:
+ case REPLACED:
+ if (!force || remoteFile == null) {
+ throw error("update not possible. file is " + state.name().toLowerCase() + ". " +
+ "Specify --force to overwrite existing files.");
+ }
+ return doUpdate(remoteFile, false);
+
+ case ADDED:
+ if (remoteFile != null) {
+ if (mergeableWithRemote(remoteFile) != FileAction.VOID) {
+ throw error("Failed to add file: object of the same name already exists.");
+ }
+ return doUpdate(remoteFile, false);
+ } else {
+ return FileAction.VOID;
+ }
+
+ case CLEAN:
+ if (remoteFile == null) {
+ return doDelete(false);
+ } else {
+ if (file.isDirectory()) {
+ // do nothing
+ return FileAction.VOID;
+ } else {
+ return doUpdate(remoteFile, false);
+ }
+ }
+
+ case CONFLICTED:
+ if (remoteFile == null) {
+ try {
+ if (!entry.revertConflict(file)) {
+ return FileAction.CONFLICTED;
+ }
+ } catch (IOException e) {
+ throw exception("Error during update.", e);
+ }
+ // refetch status, and delete file if clean
+ return doDelete(getStatus() != State.CLEAN);
+ } else {
+ try {
+ if (!entry.revertConflict(file)) {
+ return doMerge(remoteFile, FileAction.CONFLICTED);
+ } else {
+ return doMerge(remoteFile, FileAction.UPDATED);
+ }
+ } catch (IOException e) {
+ throw exception("Error during update.", e);
+ }
+ }
+
+ case DELETED:
+ if (remoteFile == null) {
+ // we can delete the entry since someone else deleted it as well
+ return doDelete(false);
+ } else {
+ // just update base and entry, in case someone wants to revert
+ return doUpdate(remoteFile, true);
+ }
+
+ case MISSING:
+ if (remoteFile == null) {
+ // if file is missing, just delete it
+ return doDelete(false);
+ } else {
+ // do update
+ entry = null;
+ return doUpdate(remoteFile, false);
+ }
+
+ case MODIFIED:
+ if (remoteFile == null) {
+ // keep the file
+ return doDelete(true);
+ } else {
+ return doMerge(remoteFile, FileAction.VOID);
+ }
+
+ case UNKNOWN:
+ if (remoteFile == null) {
+ // do nothing
+ return FileAction.VOID;
+ } else {
+ // do update
+ if (file.exists() && !force) {
+ throw error("Failed to update: object of the same name already exists." +
+ " Specify --force to overwrite existing files.");
+ }
+ return doUpdate(remoteFile, false);
+ }
+
+ case VOID:
+ // do update
+ return doUpdate(remoteFile, false);
+
+ default:
+ throw exception("illegal state: " + state, null);
+ }
+ }
+
+ public FileAction status(VaultFile remoteFile) throws VltException {
+ State state = getStatus();
+ switch (state) {
+ case IGNORED:
+ case OBSTRUCTED:
+ case REPLACED:
+ return FileAction.CONFLICTED;
+
+ case ADDED:
+ if (remoteFile != null) {
+ return FileAction.CONFLICTED;
+ } else {
+ return FileAction.VOID;
+ }
+
+ case CLEAN:
+ if (remoteFile == null) {
+ return FileAction.DELETED;
+ } else {
+ if (file.isDirectory()) {
+ // do nothing
+ return FileAction.VOID;
+ } else {
+ return equalsToRemote(remoteFile)
+ ? FileAction.VOID
+ : FileAction.UPDATED;
+ }
+ }
+
+ case CONFLICTED:
+ // do not probe further
+ return FileAction.CONFLICTED;
+
+ case DELETED:
+ return FileAction.VOID;
+
+ case MISSING:
+ return FileAction.ADDED;
+
+ case MODIFIED:
+ if (remoteFile == null) {
+ return FileAction.DELETED;
+ } else {
+ return mergeableWithRemote(remoteFile);
+ }
+
+ case UNKNOWN:
+ if (remoteFile == null) {
+ // do nothing
+ return FileAction.VOID;
+ } else {
+ return FileAction.UPDATED;
+ }
+
+ case VOID:
+ return FileAction.ADDED;
+
+ default:
+ throw exception("illegal state: " + state, null);
+ }
+ }
+
+ public FileAction add(boolean force) throws VltException {
+ State state = getStatus();
+ switch (state) {
+ case ADDED:
+ case CLEAN:
+ case CONFLICTED:
+ case MISSING:
+ case MODIFIED:
+ case OBSTRUCTED:
+ case REPLACED:
+ parent.getContext().printMessage(this, "is already under version control");
+ break;
+ case DELETED:
+ parent.getContext().printMessage(this, "replace not supported yet");
+ break;
+ case IGNORED:
+ parent.getContext().printMessage(this, "failed to add. is ignored.");
+ break;
+ case UNKNOWN:
+ case VOID:
+ return doAdd(force);
+ }
+ return FileAction.VOID;
+ }
+
+ private FileAction doAdd(boolean force) throws VltException {
+ assert entry == null;
+ entry = parent.getEntries().update(getName(), null, null);
+ VltEntryInfo work = entry.create(VltEntryInfo.Type.WORK);
+ try {
+ work.update(file, true);
+ } catch (IOException e) {
+ throw exception("Error while adding file", e);
+ }
+ String contentType = MimeTypes.getMimeType(file.getName(), MimeTypes.APPLICATION_OCTET_STREAM);
+ work.setContentType(contentType);
+ entry.put(work);
+ return FileAction.ADDED;
+ }
+
+ private FileAction doDelete(boolean keepFile)
+ throws VltException {
+ // small hack to remove meta directory. should actually be somewhere else
+ if (file.isDirectory()) {
+ VltDirectory dir = new VltDirectory(parent.getContext(), file);
+ dir.uncontrol();
+ } else {
+ try {
+ if (getBaseFile(false) != null) {
+ getBaseFile(false).delete();
+ }
+ } catch (IOException e) {
+ throw new VltException(getPath(), "Error while deleting base file.", e);
+ }
+ }
+ if (!keepFile) {
+ file.delete();
+ }
+ entry = null;
+ return FileAction.DELETED;
+ }
+
+ private FileAction doMerge(VaultFile remoteFile, FileAction action)
+ throws VltException {
+ if (remoteFile.isDirectory()) {
+ throw exception("Error while merging. remote is a directory.", null);
+ }
+ // abort merger if actions is already conflict
+ if (action == FileAction.CONFLICTED) {
+ return action;
+ }
+ MetaFile baseFile = getBaseFile(false);
+ MetaFile tmpFile = getTmpFile();
+
+ VltEntryInfo base = entry.base();
+ VltEntryInfo work = entry.work();
+ byte[] lineFeed = MimeTypes.isBinary(remoteFile.getContentType())
+ ? null
+ : LineOutputStream.LS_NATIVE;
+
+ // get the remote file
+ VaultFileCopy copy = null;
+ boolean remoteUpdated = true;
+ try {
+ // first check size and last modified
+ if (!base.checkModified(remoteFile)) {
+ remoteUpdated = false;
+ } else {
+ File temp = tmpFile.openTempFile();
+ copy = VaultFileCopy.copy(remoteFile, temp, lineFeed);
+ // if tmp is equal to the base one, there was no update on the server
+ if (copy.getMd5().equals(base.getMd5())) {
+ tmpFile.closeTempFile(tmpFile.length() >= 0);
+ remoteUpdated = false;
+ } else {
+ tmpFile.closeTempFile(false);
+ }
+ }
+ } catch (IOException e) {
+ throw exception("Error while copying files.", e);
+ }
+ if (!remoteUpdated) {
+ if (work.getMd5().equals(base.getMd5())) {
+ // fix base
+ base.setSize(work.getSize());
+ base.setDate(work.getDate());
+ return FileAction.VOID;
+ } else if (remoteFile.lastModified() > 0) {
+ // normal modification provided
+ return action;
+ }
+ }
+
+ try {
+ // check if binary
+ boolean remoteBT = getRemoteBinaryType(remoteFile, copy);
+ boolean localBT = MimeTypes.isBinary(base.getContentType());
+ if (remoteBT || localBT) {
+ parent.getContext().printMessage(this, "can't merge. binary content");
+ entry.conflict(file, baseFile, tmpFile);
+ return FileAction.CONFLICTED;
+ }
+
+ // do a 3-way diff between the base, the local and the remote one.
+ // we currently do not use document sources, since we don't really have
+ // a label to provide (like rev. num, etc).
+ Reader r0 = baseFile.getReader();
+ Reader r1 = tmpFile.getReader();
+ Document baseDoc = new Document(null, LineElementsFactory.create(new MetaFileDocSource(baseFile), r0, false));
+ Document leftDoc = new Document(null, LineElementsFactory.create(new FileDocumentSource(file), false, Constants.ENCODING));
+ Document rightDoc = new Document(null, LineElementsFactory.create(new MetaFileDocSource(tmpFile), r1, false));
+
+ DocumentDiff3 diff;
+ try {
+ diff = baseDoc.diff3(leftDoc, rightDoc);
+ } finally {
+ IOUtils.closeQuietly(r0);
+ IOUtils.closeQuietly(r1);
+ }
+
+ // save the diff output
+ Writer out = new OutputStreamWriter(FileUtils.openOutputStream(file), Constants.ENCODING);
+ try {
+ diff.write(new DiffWriter(out), false);
+ } catch (IOException e) {
+ IOUtils.closeQuietly(out);
+ }
+
+ if (diff.hasConflicts()) {
+ entry.conflict(file, baseFile, tmpFile);
+ action = FileAction.CONFLICTED;
+ } else {
+ // make the tmp file the new base
+ tmpFile.moveTo(baseFile);
+ base.update(baseFile, true);
+ action = FileAction.MERGED;
+ }
+
+ // and update the 'work'
+ // check if MD5 changes and change action accordingly
+ MD5 oldMd5 = work.getMd5();
+ work.update(file, true);
+ if (oldMd5.equals(work.getMd5())) {
+ action = FileAction.VOID;
+ }
+ // check if remote file provided a last modified
+ if (remoteFile.lastModified() == 0) {
+ if (work.getMd5().equals(base.getMd5())) {
+ base.setDate(work.getDate());
+ } else {
+ base.setDate(System.currentTimeMillis());
+ }
+ }
+
+ } catch (IOException e) {
+ throw exception("Error during merge operation.", e);
+ }
+
+ return action;
+ }
+
+ private boolean getRemoteBinaryType(VaultFile remoteFile, VaultFileCopy copy) {
+ // check if binary
+ boolean remoteBT = MimeTypes.isBinary(remoteFile.getContentType());
+ if (copy != null && remoteBT != copy.isBinary()) {
+ parent.getContext().printMessage(this, "Remote Binary type differs from actual data. Content Type: " + remoteFile.getContentType() + " Data is binary: " + copy.isBinary() + ". Using data type.");
+ remoteBT = copy.isBinary();
+ }
+ return remoteBT;
+ }
+
+ private FileAction mergeableWithRemote(VaultFile remoteFile)
+ throws VltException {
+ if (remoteFile.isDirectory() != file.isDirectory()) {
+ return FileAction.CONFLICTED;
+ }
+ if (file.isDirectory()) {
+ return FileAction.VOID;
+ }
+
+ MetaFile tmpFile = getTmpFile();
+
+ VltEntryInfo base = entry.base();
+
+ // get the remote file
+ byte[] lineFeed = MimeTypes.isBinary(remoteFile.getContentType())
+ ? null
+ : LineOutputStream.LS_NATIVE;
+ VaultFileCopy copy;
+ try {
+ File temp = tmpFile.openTempFile();
+ copy = VaultFileCopy.copy(remoteFile, temp, lineFeed);
+ if (base == null) {
+ tmpFile.closeTempFile(true);
+ // if base is null, file was only added so check the work entry
+ VltEntryInfo work = entry.work();
+ if (copy.getMd5().equals(work.getMd5())) {
+ return FileAction.VOID;
+ } else {
+ return FileAction.CONFLICTED;
+ }
+ }
+
+ // if tmp is equal to the base one, there was not update on the server
+ if (copy.getMd5().equals(base.getMd5())) {
+ tmpFile.closeTempFile(true);
+ return FileAction.VOID;
+ }
+ // keep tmp file
+ tmpFile.closeTempFile(false);
+
+ } catch (IOException e) {
+ throw exception("Error while copying files.", e);
+ }
+
+ // check if binary
+ boolean remoteBT = getRemoteBinaryType(remoteFile, copy);
+ if (remoteBT || MimeTypes.isBinary(base.getContentType())) {
+ return FileAction.CONFLICTED;
+ }
+
+ try {
+ // do a 3-way diff between the base, the local and the remote one.
+ // we currently do not use document sources, since we don't really have
+ // a label to provide (like rev. num, etc).
+
+ MetaFile baseFile = getBaseFile(false);
+ Reader r0 = baseFile.getReader();
+ Reader r1 = tmpFile.getReader();
+ Document baseDoc = new Document(null, LineElementsFactory.create(new MetaFileDocSource(baseFile), r0, false));
+ Document leftDoc = new Document(null, LineElementsFactory.create(new FileDocumentSource(file), false, Constants.ENCODING));
+ Document rightDoc = new Document(null, LineElementsFactory.create(new MetaFileDocSource(tmpFile), r1, false));
+
+ DocumentDiff3 diff;
+ try {
+ diff = baseDoc.diff3(leftDoc, rightDoc);
+ } finally {
+ IOUtils.closeQuietly(r0);
+ IOUtils.closeQuietly(r1);
+ }
+
+ if (diff.hasConflicts()) {
+ return FileAction.CONFLICTED;
+ } else {
+ return FileAction.MERGED;
+ }
+ } catch (IOException e) {
+ throw exception("Error during merge operation.", e);
+ }
+ }
+
+ private void doRevert() throws VltException {
+ if (entry.isDirectory()) {
+ file.mkdir();
+ } else {
+ try {
+ getBaseFile(false).copyTo(getFile(), true);
+ } catch (IOException e) {
+ throw exception("Error while copying files.", e);
+ }
+ }
+ VltEntryInfo base = entry.base();
+ entry.put(base.copyAs(VltEntryInfo.Type.WORK));
+ }
+
+ private boolean equalsToRemote(VaultFile remoteFile)
+ throws VltException {
+ MetaFile tmpFile = getTmpFile();
+
+ // copy file
+ byte[] lineFeed = MimeTypes.isBinary(remoteFile.getContentType())
+ ? null
+ : LineOutputStream.LS_NATIVE;
+ VaultFileCopy copy;
+ File temp = null;
+ try {
+ temp = tmpFile.openTempFile();
+ copy = VaultFileCopy.copy(remoteFile, temp, lineFeed);
+ } catch (IOException e) {
+ throw exception("Error while copying files.", e);
+ } finally {
+ if (tmpFile != null) {
+ try {
+ tmpFile.closeTempFile(true);
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ // if md5 is equal, no update
+ VltEntryInfo base = entry.base();
+ return copy.getMd5().equals(base.getMd5());
+ }
+
+ private FileAction doUpdate(VaultFile remoteFile, boolean baseOnly)
+ throws VltException {
+ FileAction action;
+ VltEntryInfo base;
+ if (entry == null || entry.base() == null) {
+ // new entry
+ action = FileAction.ADDED;
+ entry = parent.getEntries().update(getName(), remoteFile.getAggregatePath(), remoteFile.getRepoRelPath());
+ base = entry.create(VltEntryInfo.Type.BASE);
+ entry.put(base);
+ } else {
+ action = FileAction.UPDATED;
+ base = entry.base();
+
+ // quick check if modified
+ if (!base.checkModified(remoteFile)) {
+ return FileAction.VOID;
+ }
+ }
+ long lastMod = remoteFile.lastModified();
+ if (lastMod == 0) {
+ lastMod = System.currentTimeMillis();
+ }
+ base.setDate(lastMod);
+
+ if (remoteFile.isDirectory()) {
+ if (!baseOnly) {
+ // ensure controlled
+ // todo: this does not belong here
+ if (entry.work() != null) {
+ action = FileAction.VOID;
+ } else {
+ entry.put(base.copyAs(VltEntryInfo.Type.WORK));
+ }
+ file.mkdir();
+ file.setLastModified(base.getDate());
+ VltDirectory dir = new VltDirectory(parent.getContext(), file);
+ if (!dir.isControlled()) {
+ dir.control(remoteFile.getPath(), remoteFile.getControllingAggregate().getPath());
+ action = FileAction.ADDED;
+ }
+ }
+ } else {
+ MetaFile baseFile = getBaseFile(true);
+
+ // copy file
+ byte[] lineFeed = MimeTypes.isBinary(remoteFile.getContentType())
+ ? null
+ : LineOutputStream.LS_NATIVE;
+ VaultFileCopy copy;
+ try {
+ File temp = baseFile.openTempFile();
+ copy = VaultFileCopy.copy(remoteFile, temp, lineFeed);
+ baseFile.closeTempFile(false);
+ } catch (IOException e) {
+ throw exception("Error while copying files.", e);
+ }
+ // if md5 is equal, no update
+ if (copy.getMd5().equals(base.getMd5())) {
+ action = FileAction.VOID;
+ }
+
+ if (action == FileAction.VOID
+ && (base.getContentType() != null || remoteFile.getContentType() != null)
+ && (base.getContentType() == null || !base.getContentType().equals(remoteFile.getContentType()))) {
+ action = FileAction.UPDATED;
+ }
+
+ // update infos
+ VltEntryInfo work = entry.work();
+ base.setContentType(remoteFile.getContentType());
+ base.setSize(copy.getLength());
+ base.setMd5(copy.getMd5());
+ if (!baseOnly) {
+ // only copy if not equal
+ if (work == null || !work.getMd5().equals(copy.getMd5()) || !getFile().exists()) {
+ try {
+ baseFile.copyTo(getFile(), true);
+ entry.put(base.copyAs(VltEntryInfo.Type.WORK));
+ } catch (IOException e) {
+ throw exception("Error while copying files.", e);
+ }
+ }
+ }
+ }
+ return action;
+ }
+
+ private VltException exception(String msg, Throwable cause) {
+ return parent.getContext().exception(getPath(), msg, cause);
+ }
+
+ private VltException error(String msg) {
+ return parent.getContext().error(getPath(), msg);
+ }
+
+ //-----------------------------------------------------< DocumentSource >---
+
+ public String getLabel() {
+ return getName();
+ }
+
+ public String getLocation() {
+ File cwd = parent.getContext().getCwd();
+ return PathUtil.getRelativeFilePath(cwd.getPath(), file.getPath());
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/AbstractAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/AbstractAction.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/AbstractAction.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/AbstractAction.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,59 @@
+/*
+ * 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.vault.vlt.actions;
+
+import org.apache.jackrabbit.vault.fs.api.VaultFile;
+import org.apache.jackrabbit.vault.vlt.VltDirectory;
+import org.apache.jackrabbit.vault.vlt.VltException;
+import org.apache.jackrabbit.vault.vlt.VltFile;
+
+/**
+ * <code>AbstractAction</code>...
+ *
+ */
+abstract public class AbstractAction implements Action {
+
+ private boolean onlyControlled;
+
+ public boolean onlyControlled() {
+ return onlyControlled;
+ }
+
+ public void setOnlyControlled(boolean onlyControlled) {
+ this.onlyControlled = onlyControlled;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void run(VltDirectory dir, VltFile file, VaultFile remoteFile)
+ throws VltException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return <code>true</code> if the given directory is controlled or
+ * {@link #onlyControlled} is <code>false</code>;
+ */
+ public boolean run(VltDirectory dir, VaultFile remoteDir)
+ throws VltException {
+ return dir.isControlled() || !onlyControlled;
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Action.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Action.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Action.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Action.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,58 @@
+/*
+ * 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.vault.vlt.actions;
+
+import org.apache.jackrabbit.vault.fs.api.VaultFile;
+import org.apache.jackrabbit.vault.vlt.VltContext;
+import org.apache.jackrabbit.vault.vlt.VltDirectory;
+import org.apache.jackrabbit.vault.vlt.VltException;
+import org.apache.jackrabbit.vault.vlt.VltFile;
+
+/**
+ * <code>Action</code>...
+ *
+ */
+public interface Action {
+
+ /**
+ * Executes this action on the given context.
+ * @param ctx context
+ * @throws VltException if an error occurs
+ */
+ public void run(VltContext ctx) throws VltException;
+
+ /**
+ * Executes this action for the given files.
+ * @param dir vlt directory
+ * @param file local file
+ * @param remoteFile remote file
+ * @throws VltException if an error occurs
+ */
+ public void run(VltDirectory dir, VltFile file, VaultFile remoteFile)
+ throws VltException;
+
+
+ /**
+ * Executes this action on the given directory
+ * @param dir local directory
+ * @param remoteDir remote directory
+ * @throws VltException if an error occurs
+ *
+ * @return <code>true</code> if proceed; <code>false</code> to abort
+ */
+ public boolean run(VltDirectory dir, VaultFile remoteDir) throws VltException;
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Add.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Add.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Add.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Add.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,55 @@
+/*
+ * 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.vault.vlt.actions;
+
+import java.io.File;
+import java.util.List;
+
+import org.apache.jackrabbit.vault.fs.api.VaultFile;
+import org.apache.jackrabbit.vault.vlt.FileAction;
+import org.apache.jackrabbit.vault.vlt.VltDirectory;
+import org.apache.jackrabbit.vault.vlt.VltException;
+import org.apache.jackrabbit.vault.vlt.VltFile;
+
+/**
+ * <code>Resolved</code>...
+ *
+ */
+public class Add extends BaseAction {
+
+ private boolean force;
+
+ public Add(File localDir, List<File> localFiles, boolean nonRecursive, boolean force) {
+ super(localDir, localFiles, nonRecursive);
+ setDirsAsFiles(true);
+ this.force = force;
+ }
+
+ public void run(VltDirectory dir, VltFile file, VaultFile remoteFile) throws VltException {
+ FileAction action = file.add(force);
+ dir.getContext().printAction(file, action);
+
+ // if file is a directory, put under version control
+ if (file.canDescend()) {
+ VltDirectory child = file.descend();
+ if (!child.isControlled()) {
+ // this is a bit a hack
+ child.control(dir.getEntries().getPath() + "/" + file.getName(), null);
+ }
+ }
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/BaseAction.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/BaseAction.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/BaseAction.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/BaseAction.java Sat Aug 10 05:53:42 2013
@@ -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.vault.vlt.actions;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.jackrabbit.vault.vlt.VltContext;
+import org.apache.jackrabbit.vault.vlt.VltDirectory;
+import org.apache.jackrabbit.vault.vlt.VltException;
+import org.apache.jackrabbit.vault.vlt.meta.Ignored;
+
+/**
+ * Basic implementation of an abstract action
+ */
+public class BaseAction extends AbstractAction {
+
+ private final File localDir;
+
+ private final List<File> localFiles;
+
+ private final boolean nonRecursive;
+
+ private boolean dirsAsFiles;
+
+ private boolean withRemote;
+
+ public BaseAction(File localDir, List<File> localFiles, boolean nonRecursive) {
+ this.localDir = localDir;
+ this.localFiles = localFiles == null ? new LinkedList<File>() : localFiles;
+ this.nonRecursive = nonRecursive;
+ }
+
+ public boolean isWithRemote() {
+ return withRemote;
+ }
+
+ public void setWithRemote(boolean withRemote) {
+ this.withRemote = withRemote;
+ }
+
+ public void setDirsAsFiles(boolean dirsAsFiles) {
+ this.dirsAsFiles = dirsAsFiles;
+ }
+
+ public void run(VltContext ctx, VltTree infos) throws VltException {
+ if (withRemote) {
+ for (VltTree.Info i: infos.infos()) {
+ i.dir.applyWithRemote(this, i.names, nonRecursive);
+ }
+ } else {
+ for (VltTree.Info i: infos.infos()) {
+ // special check for jcr_root
+ if (!ctx.getExportRoot().getJcrRoot().getParentFile().equals(i.dir.getDirectory())) {
+ i.dir.assertControlled();
+ }
+ i.dir.apply(this, i.names, nonRecursive);
+ }
+ }
+ }
+
+ public void run(VltContext ctx) throws VltException {
+ VltTree infos = new VltTree(ctx, nonRecursive);
+ infos.setDirsAsFiles(dirsAsFiles);
+ try {
+ if (localFiles.isEmpty()) {
+ infos.add(localDir);
+ } else {
+ infos.addAll(localFiles);
+ }
+ } catch (IOException e) {
+ throw new VltException("Unable to perform command.", e);
+ }
+ // get common ancestor
+ VltDirectory root = new VltDirectory(ctx, new File(infos.getRootPath()));
+ // mount fs at the top most directory
+ if (root.isControlled()) {
+ ctx.setFsRoot(root);
+ }
+ // define globally ignored
+ ctx.setGlobalIgnored(new Ignored(ctx, root.getDirectory()));
+
+ run(ctx, infos);
+ }
+
+}
\ No newline at end of file