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 [38/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/meta/VltEntryInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/VltEntryInfo.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/VltEntryInfo.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/VltEntryInfo.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,71 @@
+/*
+ * 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.meta;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.jackrabbit.vault.fs.api.VaultFile;
+import org.apache.jackrabbit.vault.util.MD5;
+
+/**
+ * <code>Entry</code>...
+ *
+ */
+public interface VltEntryInfo {
+
+ public enum Type {
+ BASE,
+ WORK,
+ MINE,
+ THEIRS
+ }
+
+ VltEntryInfo copyAs(Type type);
+
+ Type getType();
+
+ long getDate();
+
+ void setDate(long date);
+
+ MD5 getMd5();
+
+ void setMd5(MD5 md5);
+
+ String getContentType();
+
+ void setContentType(String contentType);
+
+ long getSize();
+
+ void setSize(long size);
+
+ boolean checkModified(VaultFile remoteFile);
+
+ void update(VltEntryInfo base);
+
+ void update(File file, boolean force) throws IOException;
+
+ void update(MetaFile file, boolean force) throws IOException;
+
+ boolean isDirectory();
+
+ boolean isSame(VltEntryInfo base);
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntries.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntries.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntries.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntries.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,161 @@
+/*
+ * 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.meta.bin;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.jackrabbit.vault.fs.api.DumpContext;
+import org.apache.jackrabbit.vault.vlt.VltFile;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntries;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <code>BinEntries</code>...
+ */
+public class BinEntries implements VltEntries {
+
+ /**
+ * default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(BinEntries.class);
+
+ protected final BinMetaFile file;
+
+ private String path;
+
+ private Map<String, VltEntry> entries;
+
+ public BinEntries(File file) {
+ this.file = new BinMetaFile(file);
+ }
+
+ public boolean exists() {
+ return file.exists();
+ }
+
+ public void close() {
+ try {
+ file.close();
+ } catch (IOException e) {
+ log.warn("Error while closing entries", e);
+ }
+ }
+
+ public void create(String path) throws IOException {
+ HeaderBlock header = file.open();
+ PropertiesBlock pBlk = file.getLinkedBlock(header, 0, PropertiesBlock.class, true);
+ pBlk.setProperty("path", path);
+ file.sync();
+ this.path = path;
+ }
+
+ private void loadPaths() {
+ if (path == null) {
+ try {
+ HeaderBlock header = file.open();
+ PropertiesBlock pBlk = file.getLinkedBlock(header, 0, PropertiesBlock.class, true);
+ path = pBlk.getProperty("path");
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ public String getPath() {
+ loadPaths();
+ return path;
+ }
+
+ public void update(VltFile file) {
+ VltEntry e = file.getEntry();
+ if (e == null) {
+ BinEntry old = (BinEntry) entries.remove(file.getName());
+ if (old != null) {
+ try {
+ this.file.delete(old.block);
+ } catch (IOException e1) {
+ throw new IllegalStateException(e1);
+ }
+ }
+ }
+ }
+
+ public VltEntry getEntry(String localName) {
+ entries();
+ return entries.get(localName);
+ }
+
+ public VltEntry update(String localName, String aggregatePath, String repoRelPath) {
+ entries();
+
+ EntryBlock blk = new EntryBlock(localName, aggregatePath, repoRelPath);
+ BinEntry e = new BinEntry(this, blk);
+
+ BinEntry old = (BinEntry) entries.remove(localName);
+ if (old != null) {
+ e.put(old.work());
+ e.put(old.base());
+ e.put(old.mine());
+ e.put(old.theirs());
+ try {
+ this.file.delete(old.block);
+ } catch (IOException e1) {
+ throw new IllegalStateException(e1);
+ }
+ }
+ file.add(blk);
+ entries.put(localName, e);
+ return e;
+ }
+
+ public boolean hasEntry(String localName) {
+ entries();
+ return entries.containsKey(localName);
+ }
+
+ public Collection<VltEntry> entries() {
+ try {
+ if (entries == null) {
+ entries = new HashMap<String, VltEntry>();
+ file.open();
+ Iterator<Block> iter = file.blocks();
+ while (iter.hasNext()) {
+ Block blk = iter.next();
+ if (blk instanceof EntryBlock) {
+ VltEntry e = new BinEntry(this, (EntryBlock) blk);
+ entries.put(e.getName(), e);
+ }
+ }
+ }
+ return entries.values();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void dump(DumpContext ctx, boolean isLast) {
+ file.dump(ctx, isLast);
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntry.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntry.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntry.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntry.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,175 @@
+/*
+ * 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.meta.bin;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.EnumMap;
+import java.util.Map;
+
+import org.apache.jackrabbit.vault.vlt.meta.MetaFile;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntry;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntryInfo;
+
+/**
+ * <code>BinEntry</code>...
+ */
+public class BinEntry implements VltEntry {
+
+ private final BinEntries entries;
+
+ protected final EntryBlock block;
+
+ private Map<VltEntryInfo.Type, VltEntryInfo> infos =
+ new EnumMap<VltEntryInfo.Type, VltEntryInfo>(VltEntryInfo.Type.class);
+
+
+ public BinEntry(BinEntries entries, EntryBlock block) {
+ this.entries = entries;
+ this.block = block;
+
+ try {
+ init(VltEntryInfo.Type.BASE, EntryBlock.ID_BASE);
+ init(VltEntryInfo.Type.WORK, EntryBlock.ID_WORK);
+ init(VltEntryInfo.Type.MINE, EntryBlock.ID_MINE);
+ init(VltEntryInfo.Type.THEIRS, EntryBlock.ID_THEIRS);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private void init(VltEntryInfo.Type type, int id) throws IOException {
+ InfoBlock blk = entries.file.getLinkedBlock(block, id, InfoBlock.class, false);
+ if (blk != null) {
+ infos.put(type, new BinEntryInfo(type, blk));
+ }
+ }
+ public String getName() {
+ return block.getName();
+ }
+
+ public String getRepoRelPath() {
+ return block.getRelPath();
+ }
+
+ public String getAggregatePath() {
+ return block.getAggregatePath();
+ }
+
+ public VltEntryInfo create(VltEntryInfo.Type type) {
+ return new BinEntryInfo(type, new InfoBlock());
+ }
+
+ public void put(VltEntryInfo info) {
+ if (info == null) {
+ return;
+ }
+ BinEntryInfo old = (BinEntryInfo) infos.put(info.getType(), info);
+ Block newBlk = ((BinEntryInfo) info).block;
+ if (old != null) {
+ // need to save the offset
+ newBlk.offset = old.block.offset;
+ } else {
+ try {
+ switch (info.getType()) {
+ case BASE:
+ entries.file.linkBlock(block, EntryBlock.ID_BASE, newBlk);
+ break;
+ case MINE:
+ entries.file.linkBlock(block, EntryBlock.ID_MINE, newBlk);
+ break;
+ case THEIRS:
+ entries.file.linkBlock(block, EntryBlock.ID_THEIRS, newBlk);
+ break;
+ case WORK:
+ entries.file.linkBlock(block, EntryBlock.ID_WORK, newBlk);
+ break;
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ public VltEntryInfo work() {
+ return infos.get(VltEntryInfo.Type.WORK);
+ }
+
+ public VltEntryInfo base() {
+ return infos.get(VltEntryInfo.Type.BASE);
+ }
+
+ public VltEntryInfo mine() {
+ return infos.get(VltEntryInfo.Type.MINE);
+ }
+
+ public VltEntryInfo theirs() {
+ return infos.get(VltEntryInfo.Type.THEIRS);
+ }
+
+
+ public VltEntryInfo remove(VltEntryInfo.Type type) {
+ BinEntryInfo old = (BinEntryInfo) infos.remove(type);
+ if (old != null) {
+ switch (type) {
+ case BASE:
+ block.linkModified(0, EntryBlock.ID_BASE);
+ break;
+ case MINE:
+ block.linkModified(0, EntryBlock.ID_MINE);
+ break;
+ case THEIRS:
+ block.linkModified(0, EntryBlock.ID_THEIRS);
+ break;
+ case WORK:
+ block.linkModified(0, EntryBlock.ID_WORK);
+ break;
+ }
+ }
+ return old;
+ }
+
+ public State getState() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void resolved(MetaFile fileTmp, File fileWork, MetaFile fileBase) throws IOException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean delete(File fileWork) {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean revertConflict(File work) throws IOException {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void conflict(File work, MetaFile base, MetaFile tmp) throws IOException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isDirty() {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isDirectory() {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntryInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntryInfo.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntryInfo.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinEntryInfo.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,105 @@
+/*
+ * 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.meta.bin;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.jackrabbit.vault.fs.api.VaultFile;
+import org.apache.jackrabbit.vault.util.MD5;
+import org.apache.jackrabbit.vault.vlt.meta.MetaFile;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntryInfo;
+
+/**
+ * <code>BinEntryInfo</code>...
+ */
+public class BinEntryInfo implements VltEntryInfo {
+
+ protected final Type type;
+
+ protected final InfoBlock block;
+
+ public BinEntryInfo(Type type, InfoBlock block) {
+ this.type = type;
+ this.block = block;
+ }
+
+ public VltEntryInfo copyAs(Type type) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public long getDate() {
+ return block.getDate();
+ }
+
+ public void setDate(long date) {
+ block.setDate(date);
+ }
+
+ public MD5 getMd5() {
+ return block.getMd5();
+ }
+
+ public void setMd5(MD5 md5) {
+ block.setMd5(md5);
+ }
+
+ public String getContentType() {
+ return block.getContentType();
+ }
+
+ public void setContentType(String contentType) {
+ block.setContentType(contentType);
+ }
+
+ public long getSize() {
+ return block.getSize();
+ }
+
+ public void setSize(long size) {
+ block.setSize(size);
+ }
+
+ public boolean checkModified(VaultFile remoteFile) {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void update(VltEntryInfo base) {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void update(File file, boolean force) throws IOException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void update(MetaFile file, boolean force) throws IOException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isDirectory() {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isSame(VltEntryInfo base) {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinMetaDir.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinMetaDir.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinMetaDir.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinMetaDir.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,99 @@
+/*
+ * 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.meta.bin;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.jackrabbit.vault.fs.api.DumpContext;
+import org.apache.jackrabbit.vault.vlt.VltException;
+import org.apache.jackrabbit.vault.vlt.meta.MetaDirectory;
+import org.apache.jackrabbit.vault.vlt.meta.MetaFile;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntries;
+
+/**
+ * <code>MetaDir</code>...
+ */
+public class BinMetaDir implements MetaDirectory {
+
+ private BinMetaFile file;
+
+ public BinMetaDir(File file) {
+ this.file = new BinMetaFile(file);
+ }
+
+ public File getFile() {
+ return file.getFile();
+ }
+
+ public String getRepositoryUrl() throws IOException {
+ HeaderBlock hdr = file.open();
+ PropertiesBlock blk = file.getLinkedBlock(hdr, HeaderBlock.ID_PROPERTIES, PropertiesBlock.class, true);
+ return blk.getProperty("repository.url");
+ }
+
+ public void setRepositoryUrl(String url) throws IOException {
+ HeaderBlock hdr = file.open();
+ PropertiesBlock blk = file.getLinkedBlock(hdr, HeaderBlock.ID_PROPERTIES, PropertiesBlock.class, true);
+ blk.setProperty("repository.url", url);
+ file.sync();
+ }
+
+ public boolean exists() {
+ return file.exists();
+ }
+
+ public void create(String path) throws IOException {
+ }
+
+ public void delete() throws IOException {
+ }
+
+ public VltEntries getEntries() throws VltException {
+ return null;
+ }
+
+ public MetaFile getFile(String name) throws IOException {
+ return null;
+ }
+
+ public MetaFile getFile(String name, boolean create) throws IOException {
+ return null;
+ }
+
+ public MetaFile getTmpFile(String name, boolean create) throws IOException {
+ return null;
+ }
+
+ public MetaFile getBaseFile(String name, boolean create) throws IOException {
+ return null;
+ }
+
+ public boolean hasFile(String name) throws IOException {
+ return false;
+ }
+
+ public void sync() throws IOException {
+ }
+
+ public void close() throws IOException {
+ }
+
+ public void dump(DumpContext ctx, boolean isLast) {
+ file.dump(ctx, isLast);
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinMetaFile.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinMetaFile.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinMetaFile.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/BinMetaFile.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,367 @@
+/*
+ * 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.meta.bin;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.jackrabbit.vault.fs.api.DumpContext;
+import org.apache.jackrabbit.vault.fs.api.Dumpable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <code>MetaFile</code>...
+ */
+public class BinMetaFile implements Dumpable {
+
+ /**
+ * default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(BinMetaFile.class);
+
+ private final File file;
+
+ private RandomAccessFile raf = null;
+
+ private HeaderBlock header = null;
+
+ private Map<Long, Block> blocks = new TreeMap<Long, Block>();
+
+ private Map<Long, Link> links = new TreeMap<Long, Link>();
+
+ private List<Block> added = new LinkedList<Block>();
+
+ public BinMetaFile(File file) {
+ this.file = file;
+ }
+
+ public boolean exists() {
+ return file.exists();
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ public HeaderBlock open() throws IOException {
+ if (header == null) {
+ if (!file.exists()) {
+ file.createNewFile();
+ }
+ openRaf();
+ header = new HeaderBlock();
+ if (raf.length() == 0) {
+ header.write(raf);
+ } else {
+ raf.seek(0);
+ header.readData(raf);
+ }
+ blocks.put(0L, header);
+ }
+ return header;
+ }
+
+ public Block getBlock(long offset) throws IOException {
+ open();
+ Block block = blocks.get(offset);
+ if (block == null) {
+ if (offset >= raf.length()) {
+ return null;
+ }
+ raf.seek(offset);
+ block = Block.read(raf);
+ blocks.put(offset, block);
+ }
+ return block;
+ }
+
+ public EntryBlock getEntryBlock(String name) {
+ Iterator<Block> iter = blocks();
+ while (iter.hasNext()) {
+ Block block = iter.next();
+ if (block instanceof EntryBlock) {
+ EntryBlock e = (EntryBlock) block;
+ if (e.getName().equals(name)) {
+ return e;
+ }
+ }
+ }
+ return null;
+ }
+
+ public Iterator<Block> blocks() {
+ return new Iterator<Block>() {
+
+ private Block next = header;
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ public Block next() {
+ Block ret = next;
+ try {
+ next = getBlock(ret.next());
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ return ret;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ public DataBlock createDataBlock(long size) throws IOException {
+ DataBlock d = new DataBlock(size);
+ raf.seek(raf.length());
+ d.offset = raf.getFilePointer();
+ d.writeHeader(raf);
+ if (size > 0) {
+ raf.seek(raf.getFilePointer() + size - 1);
+ raf.write(0);
+ }
+ blocks.put(d.offset, d);
+ return d;
+ }
+
+ public DataBlock createDataBlock(byte[] buffer) throws IOException {
+ DataBlock d = new DataBlock(buffer.length);
+ raf.seek(raf.length());
+ d.offset = raf.getFilePointer();
+ d.writeHeader(raf);
+ raf.write(buffer);
+ blocks.put(d.offset, d);
+ return d;
+ }
+
+ public DataBlock createDataBlock(InputStream in) throws IOException {
+ DataBlock d = new DataBlock(0);
+ raf.seek(raf.length());
+ d.offset = raf.getFilePointer();
+ byte[] buffer = new byte[4096];
+ int rd;
+ while ((rd = in.read(buffer)) > 0) {
+ raf.write(buffer, 0, rd);
+ d.length += rd;
+ }
+ raf.seek(d.offset);
+ d.writeHeader(raf);
+ blocks.put(d.offset, d);
+ return d;
+ }
+
+ public byte[] getBytes(DataBlock blk) throws IOException {
+ byte[] buf = new byte[(int)blk.length - 8];
+ raf.seek(blk.offset + 8);
+ raf.read(buf);
+ return buf;
+ }
+
+ public InputStream getInputStream(DataBlock blk) throws IOException {
+ raf.seek(blk.offset + 8);
+ final long end = blk.offset + blk.length;
+ return new InputStream() {
+
+ public int read() throws IOException {
+ if (raf.getFilePointer() < end) {
+ return raf.read();
+ } else {
+ return -1;
+ }
+ }
+
+ public int read(byte b[]) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ public int read(byte b[], int off, int len) throws IOException {
+ if (end - raf.getFilePointer() < len) {
+ len = (int) (end - raf.getFilePointer());
+ }
+ if (len == 0) {
+ return -1;
+ }
+ return raf.read(b, off, len);
+ }
+ };
+ }
+
+ public void delete(Block blk) throws IOException {
+ if (blk != null) {
+ for (long o: blk.getOffsets()) {
+ if (o > 0) {
+ delete(getBlock(o));
+ }
+ }
+ invalidate(blk);
+ }
+ }
+
+ private void invalidate(Block blk) {
+ InvalidBlock ib = new InvalidBlock(blk.offset, blk.length);
+ ib.modified = true;
+ blocks.put(ib.offset, ib);
+ }
+
+ public void linkBlock(Block block, int id, Block target) throws IOException {
+ Link link = links.get(block.offset + id);
+ if (link == null) {
+ long offset = block.getLinkOffset(id);
+ if (offset != 0) {
+ invalidate(getBlock(offset));
+ }
+ link = new Link(block, target, id);
+ } else {
+ invalidate(link.target);
+ }
+ links.put(link.getKey(), link);
+ block.linkModified(target.offset, id);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends Block> T getLinkedBlock(Block block, int id, Class<T> type, boolean create)
+ throws IOException {
+ Link link = links.get(block.offset + id);
+ if (link == null) {
+ long offset = block.getLinkOffset(id);
+ T blk;
+ if (offset == 0) {
+ if (!create) {
+ return null;
+ }
+ try {
+ blk = type.newInstance();
+ } catch (Exception e) {
+ throw new InternalError(e.toString());
+ }
+ } else {
+ blk = (T) getBlock(offset);
+ }
+ link = new Link(block, blk, id);
+ links.put(link.getKey(), link);
+ }
+ return (T) link.target;
+ }
+
+ public void add(Block block) {
+ added.add(block);
+ }
+
+ public void dump(DumpContext ctx, boolean isLast) {
+ try {
+ open();
+ raf.seek(header.length());
+ Block block = header;
+ while (block != null) {
+ block.dump(ctx, isLast);
+ block = Block.read(raf);
+ }
+ } catch (IOException e) {
+ log.error("Error while accessing file", e);
+ }
+ }
+
+ public void sync() throws IOException {
+ raf.seek(raf.length());
+
+ // first check the linked blocks
+ for (Link link: links.values()) {
+ Block block = link.target;
+ if (block.needsRelocate()) {
+ if (block.offset > 0) {
+ // invalidate old block
+ InvalidBlock ib = new InvalidBlock(block.offset, block.length);
+ ib.modified = true;
+ blocks.put(block.offset, ib);
+ }
+ block.write(raf);
+ blocks.put(block.offset, block);
+ link.block.linkModified(block.offset, link.id);
+ }
+ }
+
+ // write new blocks
+ for (Block block: added) {
+ block.write(raf);
+ blocks.put(block.offset, block);
+ }
+ added.clear();
+
+ // then write modified
+ for (Block block: blocks.values()) {
+ if (block.isModified()) {
+ raf.seek(block.offset);
+ block.write(raf);
+ }
+ }
+ }
+
+ protected RandomAccessFile openRaf() throws FileNotFoundException {
+ if (raf == null) {
+ raf = new RandomAccessFile(file, "rw");
+ }
+ return raf;
+ }
+
+ public void close() throws IOException {
+ if (raf != null) {
+ sync();
+ try {
+ raf.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ raf = null;
+ }
+ header = null;
+ }
+
+ public static long getLong(byte[] b, int offs) {
+ return ((long) (b[offs] & 0xFF) << 56) +
+ ((long) (b[1 + offs] & 0xFF) << 48) +
+ ((long) (b[2 + offs] & 0xFF) << 40) +
+ ((long) (b[3 + offs] & 0xFF) << 32) +
+ ((long) (b[4 + offs] & 0xFF) << 24) +
+ ((long) (b[5 + offs] & 0xFF) << 16) +
+ ((long) (b[6 + offs] & 0xFF) << 8) +
+ ((long) (b[7 + offs] & 0xFF));
+ }
+
+ public static void setLong(byte[] b, int offs, long v) {
+ b[offs] = (byte) ((v >>> 56) & 0xFF);
+ b[offs+1] = (byte) ((v >>> 48) & 0xFF);
+ b[offs+2] = (byte) ((v >>> 40) & 0xFF);
+ b[offs+3] = (byte) ((v >>> 32) & 0xFF);
+ b[offs+4] = (byte) ((v >>> 24) & 0xFF);
+ b[offs+5] = (byte) ((v >>> 16) & 0xFF);
+ b[offs+6] = (byte) ((v >>> 8) & 0xFF);
+ b[offs+7] = (byte) ((v >>> 0) & 0xFF);
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/Block.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/Block.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/Block.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/Block.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,182 @@
+/*
+ * 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.meta.bin;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import org.apache.jackrabbit.vault.fs.api.DumpContext;
+import org.apache.jackrabbit.vault.fs.api.Dumpable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <code>Block</code>...
+ */
+public abstract class Block implements Dumpable {
+
+ /**
+ * default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(Block.class);
+
+ private static final long[] EMPTY_LONG_ARRAY = new long[0];
+
+ public static final byte TYPE_INVALID = 0;
+
+ public static final byte TYPE_HEADER = 1;
+
+ public static final byte TYPE_DATA = 2;
+
+ public static final byte TYPE_INFO = 3;
+
+ public static final byte TYPE_ENTRY = 4;
+
+ public static final byte TYPE_PROPS = 5;
+
+ protected long length;
+
+ protected long offset;
+
+ protected boolean modified;
+
+ protected boolean relocate;
+
+ protected Block() {
+ relocate = true;
+ length = 8;
+ }
+
+ public Block(long offset, long length) {
+ this.offset = offset;
+ this.length = length;
+ }
+
+ public long length() {
+ return length;
+ }
+
+ public long offset() {
+ return offset;
+ }
+
+ public long next() {
+ return offset + length;
+ }
+
+ public static Block read(RandomAccessFile raf) throws IOException {
+ long offset = raf.getFilePointer();
+ if (offset >= raf.length()) {
+ return null;
+ }
+ byte[] tlen = new byte[8];
+ raf.read(tlen);
+ byte type = tlen[0];
+ tlen[0] = 0;
+ long length = BinMetaFile.getLong(tlen, 0);
+ Block blk;
+ switch (type) {
+ case TYPE_INVALID:
+ blk = new InvalidBlock(offset, length);
+ break;
+ case TYPE_DATA:
+ blk = new DataBlock(offset, length);
+ break;
+ case TYPE_INFO:
+ blk = new InfoBlock(offset, length);
+ break;
+ case TYPE_ENTRY:
+ blk = new EntryBlock(offset, length);
+ break;
+ case TYPE_PROPS:
+ blk = new PropertiesBlock(offset, length);
+ break;
+ default:
+ throw new InternalError("invalid block type " + type);
+ }
+ blk.readData(raf);
+ raf.seek(blk.next());
+ return blk;
+ }
+
+ protected void writeHeader(RandomAccessFile raf) throws IOException {
+ byte[] tlen = new byte[8];
+ BinMetaFile.setLong(tlen, 0, length);
+ tlen[0] = getType();
+ raf.write(tlen);
+ }
+
+ public void write(RandomAccessFile raf) throws IOException {
+ offset = raf.getFilePointer();
+ // write (old) header
+ writeHeader(raf);
+ writeData(raf);
+ long length = raf.getFilePointer() - offset;
+
+ // write new header if length is different
+ if (length != this.length) {
+ this.length = length;
+ raf.seek(offset);
+ writeHeader(raf);
+ raf.seek(next());
+ }
+ modified = false;
+ relocate = false;
+ }
+
+ public boolean isModified() {
+ return modified;
+ }
+
+ public boolean needsRelocate() {
+ return relocate;
+ }
+
+ public long getLinkOffset(int id) {
+ return getOffsets()[id];
+ }
+
+ public void linkModified(long targetOffset, int id) {
+ final long[] offsets = getOffsets();
+ if (targetOffset != offsets[id]) {
+ offsets[id] = targetOffset;
+ modified = true;
+ }
+ }
+
+
+ public abstract byte getType();
+
+ public long[] getOffsets() {
+ return EMPTY_LONG_ARRAY;
+ }
+
+ public void readData(RandomAccessFile raf) throws IOException {
+ // do nothing
+ }
+
+ public void writeData(RandomAccessFile raf) throws IOException {
+ // just skip
+ raf.seek(offset + length);
+ }
+
+ public void dump(DumpContext ctx, boolean isLast) {
+ ctx.printf(isLast, "%08x %04x %s%n", offset, length, getClass().getSimpleName());
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/DataBlock.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/DataBlock.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/DataBlock.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/DataBlock.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,40 @@
+/*
+ * 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.meta.bin;
+
+/**
+ * <code>EntryBlock</code>...
+ */
+public class DataBlock extends Block {
+
+ public DataBlock() {
+ }
+
+ public DataBlock(long size) {
+ this(0, size + 8);
+ }
+
+ public DataBlock(long offset, long length) {
+ super(offset, length);
+ }
+
+ public byte getType() {
+ return Block.TYPE_DATA;
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/EntryBlock.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/EntryBlock.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/EntryBlock.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/EntryBlock.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,117 @@
+/*
+ * 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.meta.bin;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import org.apache.jackrabbit.vault.fs.api.DumpContext;
+
+/**
+ * <code>EntryBlock</code>...
+ */
+public class EntryBlock extends Block {
+
+ public static final int ID_WORK = 0;
+ public static final int ID_BASE = 1;
+ public static final int ID_MINE = 2;
+ public static final int ID_THEIRS = 3;
+ public static final int ID_TMP = 4;
+
+ private String name = "";
+
+ private String relPath = "";
+
+ private String aggPath = "";
+
+ private long[] offsets = new long[ID_TMP + 1];
+
+ public EntryBlock(String name, String aggPath, String relPath) {
+ this.name = name;
+ this.aggPath = aggPath;
+ this.relPath = relPath;
+ }
+
+ public EntryBlock(long offset, long length) {
+ super(offset, length);
+ }
+
+ public byte getType() {
+ return Block.TYPE_ENTRY;
+ }
+
+ public void readData(RandomAccessFile raf) throws IOException {
+ name = raf.readUTF();
+ aggPath = raf.readUTF();
+ relPath = raf.readUTF();
+ for (int i=0; i<offsets.length; i++) {
+ offsets[i] = raf.readLong();
+ }
+ }
+
+ public void writeData(RandomAccessFile raf) throws IOException {
+ raf.writeUTF(name);
+ raf.writeUTF(aggPath);
+ raf.writeUTF(relPath);
+ for (long off : offsets) {
+ raf.writeLong(off);
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ relocate = true;
+ }
+
+ public String getRelPath() {
+ return relPath;
+ }
+
+ public void setRelPath(String relPath) {
+ this.relPath = relPath;
+ relocate = true;
+ }
+
+ public String getAggregatePath() {
+ return aggPath;
+ }
+
+ public void setAggregatePath(String aggPath) {
+ this.aggPath = aggPath;
+ relocate = true;
+ }
+
+ public long[] getOffsets() {
+ return offsets;
+ }
+
+ @Override
+ public void dump(DumpContext ctx, boolean isLast) {
+ ctx.printf(false, " name=%s%n", name);
+ ctx.printf(false, " work=%08x%n", offsets[ID_WORK]);
+ ctx.printf(false, " base=%08x%n", offsets[ID_BASE]);
+ ctx.printf(false, " mine=%08x%n", offsets[ID_MINE]);
+ ctx.printf(false, " thrs=%08x%n", offsets[ID_THEIRS]);
+ ctx.printf(true, " temp=%08x%n", offsets[ID_TMP]);
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/HeaderBlock.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/HeaderBlock.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/HeaderBlock.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/HeaderBlock.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,92 @@
+/*
+ * 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.meta.bin;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import org.apache.jackrabbit.vault.fs.api.DumpContext;
+
+/**
+ * <code>HeaderBlock</code>
+ */
+public class HeaderBlock extends Block {
+
+ private static final byte[] MAGIC = new byte[]{'V', 'L', 'T'};
+
+ private static final byte VERSION_1 = 1;
+
+ private static final int LENGTH = 4 + 8;
+
+ private static final int OFFSET_VERSION = 3;
+
+ private byte version = VERSION_1;
+
+ private long[] offsets = new long[1];
+
+ public static final int ID_PROPERTIES = 0;
+
+ public HeaderBlock() {
+ super(0, LENGTH);
+ }
+
+ public byte getVersion() {
+ return version;
+ }
+
+ public void setVersion(byte version) {
+ this.version = version;
+ modified = true;
+ }
+
+ public long[] getOffsets() {
+ return offsets;
+ }
+
+ public void readData(RandomAccessFile raf) throws IOException {
+ byte[] data = new byte[4];
+ raf.read(data);
+ if (data[0] != MAGIC[0] || data[1] != MAGIC[1] || data[2] != MAGIC[2]) {
+ throw new IllegalArgumentException("invalid magic " + new String(data, 0, 3));
+ }
+ version = data[OFFSET_VERSION];
+ if (version > VERSION_1) {
+ throw new IllegalArgumentException("unsupported version " + version);
+ }
+ offsets[0] = raf.readLong();
+ }
+
+ public void write(RandomAccessFile raf) throws IOException {
+ raf.seek(0);
+ raf.write(MAGIC);
+ raf.writeByte(version);
+ raf.writeLong(offsets[0]);
+ modified = false;
+ }
+
+ public byte getType() {
+ return Block.TYPE_HEADER;
+ }
+
+ @Override
+ public void dump(DumpContext ctx, boolean isLast) {
+ ctx.printf(false, "HeaderBlock%n");
+ ctx.printf(false, " version=%d%n", version);
+ ctx.printf(false, " propOff=%08x%n", offsets[0]);
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/InfoBlock.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/InfoBlock.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/InfoBlock.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/InfoBlock.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,140 @@
+/*
+ * 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.meta.bin;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import org.apache.jackrabbit.vault.fs.api.DumpContext;
+import org.apache.jackrabbit.vault.util.MD5;
+
+/**
+ * <code>InfoBlock</code>...
+ */
+public class InfoBlock extends Block {
+
+ public static final int ID_DATA = 0;
+
+ public static final int ID_PROPS = 1;
+
+ private long size;
+
+ private long date;
+
+ private long[] offsets = new long[ID_PROPS + 1];
+
+ private long md5Msb;
+
+ private long md5Lsb;
+
+ private String contentType = "";
+
+ public InfoBlock() {
+ }
+
+ public InfoBlock(long offset, long length) {
+ super(offset, length);
+ }
+
+ public byte getType() {
+ return Block.TYPE_INFO;
+ }
+
+ public void readData(RandomAccessFile raf) throws IOException {
+ size = raf.readLong();
+ date = raf.readLong();
+ for (int i=0; i<offsets.length; i++) {
+ offsets[i] = raf.readLong();
+ }
+ md5Msb = raf.readLong();
+ md5Lsb = raf.readLong();
+ contentType = raf.readUTF();
+ }
+
+ public void writeData(RandomAccessFile raf) throws IOException {
+ raf.writeLong(size);
+ raf.writeLong(date);
+ for (long off : offsets) {
+ raf.writeLong(off);
+ }
+ raf.writeLong(md5Msb);
+ raf.writeLong(md5Lsb);
+ raf.writeUTF(contentType);
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public void setSize(long size) {
+ if (size != this.size) {
+ this.size = size;
+ modified = true;
+ }
+ }
+
+ public long getDate() {
+ return date;
+ }
+
+ public void setDate(long date) {
+ if (this.date != date) {
+ this.date = date;
+ modified = true;
+ }
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public void setContentType(String contentType) {
+ if (!contentType.equals(this.contentType)) {
+ this.contentType = contentType;
+ relocate = true;
+ }
+ }
+
+ public MD5 getMd5() {
+ return new MD5(md5Msb, md5Lsb);
+ }
+
+ public void setMd5(MD5 md5) {
+ if (md5Msb != md5.getMsb() || md5Lsb != md5.getLsb()) {
+ md5Msb = md5.getMsb();
+ md5Lsb = md5.getLsb();
+ modified = true;
+ }
+ }
+
+ public long[] getOffsets() {
+ return offsets;
+ }
+
+ @Override
+ public void dump(DumpContext ctx, boolean isLast) {
+ super.dump(ctx, isLast);
+ ctx.printf(false, " size=%d%n", size);
+ ctx.printf(false, " date=%d%n", date);
+ ctx.printf(false, " data=%08x%n", offsets[ID_DATA]);
+ ctx.printf(false, " md5=%s%n", getMd5().toString());
+ ctx.printf(false, " type=%s%n", contentType);
+ ctx.printf(true, " props=%08x%n", offsets[ID_PROPS]);
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/InvalidBlock.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/InvalidBlock.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/InvalidBlock.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/InvalidBlock.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,33 @@
+/*
+ * 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.meta.bin;
+
+/**
+ * <code>EntryBlock</code>...
+ */
+public class InvalidBlock extends Block {
+
+ public InvalidBlock(long offset, long length) {
+ super(offset, length);
+ }
+
+ public byte getType() {
+ return Block.TYPE_INVALID;
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/Link.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/Link.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/Link.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/Link.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,40 @@
+/*
+ * 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.meta.bin;
+
+/**
+ * <code>Link</code>...
+ */
+public class Link {
+
+ protected final Block block;
+
+ protected final Block target;
+
+ protected final int id;
+
+ public Link(Block block, Block target, int id) {
+ this.block = block;
+ this.target = target;
+ this.id = id;
+ }
+
+ public long getKey() {
+ return block.offset + id;
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/PropertiesBlock.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/PropertiesBlock.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/PropertiesBlock.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/bin/PropertiesBlock.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,81 @@
+/*
+ * 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.meta.bin;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.jackrabbit.vault.fs.api.DumpContext;
+
+/**
+ * <code>InfoBlock</code>...
+ */
+public class PropertiesBlock extends Block {
+
+ private Map<String, String> props = new HashMap<String, String>();
+
+ public PropertiesBlock() {
+ }
+
+ public PropertiesBlock(long offset, long length) {
+ super(offset, length);
+ }
+
+ public byte getType() {
+ return Block.TYPE_PROPS;
+ }
+
+ public void readData(RandomAccessFile raf) throws IOException {
+ int size = raf.readInt();
+ for (int i=0; i<size; i++) {
+ String name = raf.readUTF();
+ String v = raf.readUTF();
+ props.put(name, v);
+ }
+ }
+
+ public void writeData(RandomAccessFile raf) throws IOException {
+ raf.writeInt(props.size());
+ for (Map.Entry<String, String> e: props.entrySet()) {
+ raf.writeUTF(e.getKey());
+ raf.writeUTF(e.getValue());
+ }
+ }
+
+ public String getProperty(String name) {
+ return props.get(name);
+ }
+
+ public void setProperty(String name, String value) {
+ if (value == null) {
+ relocate = props.remove(name) != null;
+ } else {
+ relocate = !value.equals(props.put(name, value));
+ }
+ }
+
+ @Override
+ public void dump(DumpContext ctx, boolean isLast) {
+ super.dump(ctx, isLast);
+ for (Map.Entry<String, String> e: props.entrySet()) {
+ ctx.printf(false, " %s=%s%n", e.getKey(), e.getValue());
+ }
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntries.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntries.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntries.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntries.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,221 @@
+/*
+ * 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.meta.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.jackrabbit.vault.util.xml.serialize.OutputFormat;
+import org.apache.jackrabbit.vault.util.xml.serialize.XMLSerializer;
+import org.apache.jackrabbit.vault.vlt.VltException;
+import org.apache.jackrabbit.vault.vlt.VltFile;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntries;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntry;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * <code>Entries</code>...
+ *
+ */
+public class XmlEntries implements VltEntries {
+
+ public static final String EN_ENTRIES = "entries";
+
+ public static final String AN_PATH = "path";
+
+ public static final String AN_AGGREGATE_PATH = "aggregatePath";
+
+ private final String path;
+
+ private Map<String, VltEntry> entries = new HashMap<String, VltEntry>();
+
+ private boolean dirty;
+
+ public XmlEntries(String path) {
+ this.path = path;
+ }
+
+ public XmlEntries(String path, boolean dirty) {
+ this.path = path;
+ this.dirty = dirty;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public static XmlEntries load(InputStream in) throws VltException {
+ InputSource source = new InputSource(in);
+ return load(source);
+ }
+
+ public static XmlEntries load(InputSource source) throws VltException {
+ try {
+ DocumentBuilderFactory factory =
+ DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document document = builder.parse(source);
+ Element doc = document.getDocumentElement();
+ if (!doc.getNodeName().equals(EN_ENTRIES)) {
+ throw new VltException(source.getSystemId(), "<entries> expected.");
+ }
+ // get uri
+ String path = doc.getAttribute(AN_PATH);
+ XmlEntries entries = new XmlEntries(path);
+
+ // get entries
+ NodeList nodes = doc.getChildNodes();
+ for (int i=0; i<nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+ if (node instanceof Element) {
+ Element elem = (Element) node;
+ if (elem.getNodeName().equals(XmlEntry.EN_ENTRY)) {
+ XmlEntry entry = XmlEntry.load(elem);
+ entries.entries.put(entry.getName(), entry);
+ } else {
+ throw new VltException(source.getSystemId(),
+ "<entry> expected in <entries> element.");
+ }
+ }
+ }
+ entries.dirty = false;
+ return entries;
+ } catch (ParserConfigurationException e) {
+ throw new VltException(source.getSystemId(),
+ "Unable to create configuration XML parser", e);
+ } catch (SAXException e) {
+ throw new VltException(source.getSystemId(),
+ "Configuration file syntax error.", e);
+ } catch (IOException e) {
+ throw new VltException(source.getSystemId(),
+ "Configuration file could not be read.", e);
+ }
+ }
+
+ /*
+ public void save(File file) throws VltException {
+ if (file.exists() && !isDirty()) {
+ return;
+ }
+ try {
+ FileOutputStream out = new FileOutputStream(file);
+ save(out);
+ out.close();
+ } catch (IOException e) {
+ throw new VltException(file.getPath(), "Error while saving", e);
+ }
+ }
+ */
+
+ public void save(OutputStream out) throws IOException {
+ OutputFormat fmt = new OutputFormat("xml", "UTF-8", true);
+ fmt.setLineWidth(0);
+ fmt.setIndent(2);
+ XMLSerializer ser = new XMLSerializer(out, fmt);
+ try {
+ write(ser);
+ } catch (SAXException e) {
+ throw new IOException(e.toString());
+ }
+ }
+
+ private void write(ContentHandler handler) throws SAXException {
+ handler.startDocument();
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", AN_PATH, "", "CDATA", path);
+ handler.startElement("", EN_ENTRIES, "", attrs);
+ for (VltEntry e: entries.values()) {
+ ((XmlEntry) e).write(handler);
+ }
+ handler.endElement("", EN_ENTRIES, "");
+ handler.endDocument();
+ dirty = false;
+ }
+
+ public void update(VltFile file) {
+ VltEntry e = file.getEntry();
+ if (e == null) {
+ entries.remove(file.getName());
+ dirty = true;
+ } else {
+ putEntry(e);
+ }
+ }
+
+ public void putEntry(VltEntry e) {
+ if (entries.get(e.getName()) != e) {
+ dirty = true;
+ entries.put(e.getName(), e);
+ }
+ }
+
+ public VltEntry getEntry(String localName) {
+ return entries.get(localName);
+ }
+
+ public VltEntry update(String localName, String aggregatePath, String repoRelPath) {
+ XmlEntry e = new XmlEntry(localName, aggregatePath, repoRelPath);
+ VltEntry old = entries.remove(localName);
+ if (old != null) {
+ e.put(old.work());
+ e.put(old.base());
+ e.put(old.mine());
+ e.put(old.theirs());
+ }
+ putEntry(e);
+ return e;
+ }
+
+ public boolean hasEntry(String localName) {
+ return entries.containsKey(localName);
+ }
+
+ public Collection<VltEntry> entries() {
+ return entries.values();
+ }
+
+ public void setDirty(boolean dirty) {
+ this.dirty = dirty;
+ }
+
+ public boolean isDirty() {
+ if (dirty) {
+ return true;
+ }
+ for (VltEntry e: entries.values()) {
+ if (e.isDirty()) {
+ return dirty = true;
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntry.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntry.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntry.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntry.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,309 @@
+/*
+ * 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.meta.xml;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.EnumMap;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.vault.util.MimeTypes;
+import org.apache.jackrabbit.vault.vlt.VltException;
+import org.apache.jackrabbit.vault.vlt.meta.MetaFile;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntry;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntryInfo;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * <code>Entry</code>...
+ *
+ */
+public class XmlEntry implements VltEntry {
+
+ public static final String CONFLICT_NAME_BASE = ".base";
+ public static final String CONFLICT_NAME_MINE = ".mine";
+ public static final String CONFLICT_NAME_THEIRS = ".theirs";
+
+ public static final String EN_ENTRY = "entry";
+
+ public static final String AN_NAME = "name";
+
+ public static final String AN_PATH = "rp";
+
+ public static final String AN_AGGREGATE_PATH = "ap";
+
+ private final String name;
+
+ private final String repoRelPath;
+
+ private final String aggregatePath;
+
+ private boolean dirty;
+
+ private Map<VltEntryInfo.Type, VltEntryInfo> infos =
+ new EnumMap<VltEntryInfo.Type, VltEntryInfo>(VltEntryInfo.Type.class);
+
+ protected XmlEntry(String name, String aggPath, String repoRelPath) {
+ this.name = name;
+ this.aggregatePath = aggPath;
+ this.repoRelPath = repoRelPath;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getRepoRelPath() {
+ return repoRelPath;
+ }
+
+ public String getAggregatePath() {
+ return aggregatePath;
+ }
+
+ public VltEntryInfo create(VltEntryInfo.Type type) {
+ return new XmlEntryInfo(type);
+ }
+
+ public void put(VltEntryInfo info) {
+ if (info != null) {
+ dirty = true;
+ infos.put(info.getType(), info);
+ }
+ }
+
+ public VltEntryInfo work() {
+ return infos.get(VltEntryInfo.Type.WORK);
+ }
+
+ public VltEntryInfo base() {
+ return infos.get(VltEntryInfo.Type.BASE);
+ }
+
+ public VltEntryInfo mine() {
+ return infos.get(VltEntryInfo.Type.MINE);
+ }
+
+ public VltEntryInfo theirs() {
+ return infos.get(VltEntryInfo.Type.THEIRS);
+ }
+
+ public VltEntryInfo remove(VltEntryInfo.Type type) {
+ dirty = true;
+ return infos.remove(type);
+ }
+
+ public State getState() {
+ if (infos.containsKey(VltEntryInfo.Type.MINE)) {
+ return State.CONFLICT;
+ }
+ if (!infos.containsKey(VltEntryInfo.Type.BASE)) {
+ return State.ADDED;
+ }
+ if (!infos.containsKey(VltEntryInfo.Type.WORK)) {
+ return State.DELETED;
+ }
+ return State.CLEAN;
+ }
+
+
+ public void resolved(MetaFile fileTmp, File fileWork, MetaFile fileBase)
+ throws IOException {
+ // cleanup files
+ XmlEntryInfo mine = (XmlEntryInfo) mine();
+ XmlEntryInfo base = (XmlEntryInfo) base();
+ XmlEntryInfo theirs = (XmlEntryInfo) theirs();
+ XmlEntryInfo work = (XmlEntryInfo) work();
+
+ // delete the .x files
+ new File(fileWork.getParentFile(), base.getName()).delete();
+ new File(fileWork.getParentFile(), mine.getName()).delete();
+ new File(fileWork.getParentFile(), theirs.getName()).delete();
+
+ // copy the tmp file to the base
+ File tmp = fileBase.openTempFile();
+ fileTmp.copyTo(tmp, true);
+ fileBase.closeTempFile(false);
+
+ // and update the infos
+ base.update(theirs);
+ base.setName(null);
+ work.update(fileWork, true);
+ remove(mine.getType());
+ remove(theirs.getType());
+ }
+
+ public boolean delete(File fileWork) {
+ // cleanup files
+ XmlEntryInfo mine = (XmlEntryInfo) mine();
+ XmlEntryInfo base = (XmlEntryInfo) base();
+ XmlEntryInfo theirs = (XmlEntryInfo) theirs();
+
+ // delete the .x files
+ if (mine != null) {
+ new File(fileWork.getParentFile(), mine.getName()).delete();
+ }
+ if (theirs != null) {
+ new File(fileWork.getParentFile(), theirs.getName()).delete();
+ }
+ if (base != null && base.getName() != null) {
+ new File(fileWork.getParentFile(), base.getName()).delete();
+ }
+ fileWork.delete();
+ if (base != null) {
+ base.setName(null);
+ }
+ remove(VltEntryInfo.Type.MINE);
+ remove(VltEntryInfo.Type.THEIRS);
+ remove(VltEntryInfo.Type.WORK);
+
+ return infos.isEmpty();
+ }
+
+ public boolean revertConflict(File work) throws IOException {
+ File dir = work.getParentFile();
+
+ XmlEntryInfo mine = (XmlEntryInfo) mine();
+ XmlEntryInfo theirs = (XmlEntryInfo) theirs();
+ XmlEntryInfo base = (XmlEntryInfo) base();
+
+ File fileMine = new File(dir, mine.getName());
+ if (!fileMine.exists()) {
+ return false;
+ }
+ // copy and delete files
+ FileUtils.copyFile(fileMine, work);
+ fileMine.delete();
+ new File(dir, theirs.getName()).delete();
+ new File(dir, base.getName()).delete();
+
+ // remove infos
+ remove(mine.getType());
+ remove(theirs.getType());
+ base.setName(null);
+
+ // hack: fix content type if it was lost
+ if (mine.getContentType() == null && base.getContentType() == null) {
+ VltEntryInfo workInfo = work();
+ if (workInfo.getContentType() == null) {
+ workInfo.setContentType(MimeTypes.getMimeType(work.getName()));
+ }
+ base.setContentType(workInfo.getContentType());
+ }
+ return true;
+ }
+
+ public void conflict(File work, MetaFile base, MetaFile tmp)
+ throws IOException {
+ File dir = work.getParentFile();
+ File fileMine = new File(dir, name + CONFLICT_NAME_MINE);
+ File fileBase = new File(dir, name + CONFLICT_NAME_BASE);
+ File fileTheirs = new File(dir, name + CONFLICT_NAME_THEIRS);
+
+ // copy the 3 files
+ FileUtils.copyFile(work, fileMine);
+ base.copyTo(fileBase, true);
+ tmp.copyTo(fileTheirs, true);
+
+ // the base gets and additional name
+ ((XmlEntryInfo) base()).setName(fileBase.getName());
+
+ // the 'work' becomes the 'mine'
+ String contentType = base().getContentType();
+ XmlEntryInfo mine = new XmlEntryInfo(VltEntryInfo.Type.MINE);
+ mine.update(fileMine, true);
+ mine.setName(fileMine.getName());
+ mine.setContentType(contentType);
+ put(mine);
+
+ // add the 'theirs' as well
+ XmlEntryInfo theirs = new XmlEntryInfo(VltEntryInfo.Type.THEIRS);
+ theirs.update(fileTheirs, true);
+ theirs.setName(fileTheirs.getName());
+ theirs.setContentType(contentType);
+ put(theirs);
+ }
+
+ public void write(ContentHandler handler) throws SAXException {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", AN_NAME, "", "CDATA", name);
+ if (repoRelPath != null) {
+ attrs.addAttribute("", AN_PATH, "", "CDATA", repoRelPath);
+ }
+ if (aggregatePath != null) {
+ attrs.addAttribute("", AN_AGGREGATE_PATH, "", "CDATA", aggregatePath);
+ }
+ handler.startElement("", EN_ENTRY, "", attrs);
+ for (VltEntryInfo info: infos.values()) {
+ ((XmlEntryInfo) info).write(handler);
+ }
+ handler.endElement("", EN_ENTRY, "");
+ dirty = false;
+ }
+
+ public boolean isDirty() {
+ if (dirty) {
+ return true;
+ }
+ for (VltEntryInfo info: infos.values()) {
+ if (((XmlEntryInfo) info).isDirty()) {
+ return dirty = true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isDirectory() {
+ VltEntryInfo base = infos.get(VltEntryInfo.Type.BASE);
+ if (base != null) {
+ return base.isDirectory();
+ }
+ VltEntryInfo work = infos.get(VltEntryInfo.Type.WORK);
+ return work != null && work.isDirectory();
+ }
+
+ protected static XmlEntry load(Element elem)
+ throws VltException {
+ assert elem.getNodeName().equals(EN_ENTRY);
+ String name = elem.getAttribute(AN_NAME);
+ if (name == null) {
+ throw new VltException("entry has no '" + AN_NAME + "' attribute");
+ }
+ String path = elem.hasAttribute(AN_PATH) ? elem.getAttribute(AN_PATH) : null;
+ String ap = elem.hasAttribute(AN_AGGREGATE_PATH) ? elem.getAttribute(AN_AGGREGATE_PATH) : null;
+
+ XmlEntry entry = new XmlEntry(name, ap, path);
+
+ // add infos
+ NodeList nodes = elem.getChildNodes();
+ for (int i=0; i<nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+ if (node instanceof Element) {
+ entry.put(XmlEntryInfo.load((Element) node));
+ }
+ }
+ entry.dirty = false;
+ return entry;
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntryInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntryInfo.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntryInfo.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/meta/xml/XmlEntryInfo.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,277 @@
+/*
+ * 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.meta.xml;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Calendar;
+
+import org.apache.jackrabbit.util.ISO8601;
+import org.apache.jackrabbit.vault.fs.api.VaultFile;
+import org.apache.jackrabbit.vault.util.MD5;
+import org.apache.jackrabbit.vault.vlt.VltException;
+import org.apache.jackrabbit.vault.vlt.meta.MetaFile;
+import org.apache.jackrabbit.vault.vlt.meta.VltEntryInfo;
+import org.w3c.dom.Element;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * <code>Entry</code>...
+ *
+ */
+public class XmlEntryInfo implements VltEntryInfo {
+
+ private static final String AN_NAME = "name";
+ private static final String AN_DATE = "date";
+ private static final String AN_MD5 = "md5";
+ private static final String AN_CONTENT_TYPE = "contentType";
+ private static final String AN_SIZE = "size";
+
+ private final Type type;
+
+ private String name;
+
+ private long date;
+
+ private MD5 md5;
+
+ private String contentType;
+
+ private long size;
+
+ private boolean dirty;
+
+ public XmlEntryInfo(Type type) {
+ this.type = type;
+ }
+
+ public VltEntryInfo copyAs(Type type) {
+ XmlEntryInfo info = new XmlEntryInfo(type);
+ info.update(this);
+ return info;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ if (this.name == null && name != null
+ || this.name != null && !this.name.equals(name)) {
+ this.name = name;
+ dirty = true;
+ }
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public long getDate() {
+ return date;
+ }
+
+ public void setDate(long date) {
+ // round to second
+ date -= date % 1000;
+ if (date != this.date) {
+ this.date = date;
+ dirty = true;
+ }
+ }
+
+ public MD5 getMd5() {
+ return md5;
+ }
+
+ public void setMd5(MD5 md5) {
+ if (this.md5 == null && md5 != null
+ || this.md5 != null && !this.md5.equals(md5)) {
+ this.md5 = md5;
+ dirty = true;
+ }
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public void setContentType(String contentType) {
+ if (this.contentType == null && contentType != null
+ || this.contentType != null && !this.contentType.equals(contentType)) {
+ this.contentType = contentType;
+ dirty = true;
+ }
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public void setSize(long size) {
+ if (size != this.size) {
+ this.size = size;
+ dirty = true;
+ }
+ }
+
+ /**
+ * Checks if the remote file is modified compared to this entry.
+ * It is modified if:
+ * - the local time is 0
+ * - the remote time is 0 or greater than this time.
+ * - the size differs
+ * - the content type differs
+ *
+ * @param remoteFile the remote file to compare with
+ * @return <code>true</code> if modified.
+ */
+ public boolean checkModified(VaultFile remoteFile) {
+ long rTime = remoteFile.lastModified();
+ rTime -= rTime % 1000;
+
+ if (date <=0 || rTime <= 0 || rTime > date) {
+ return true;
+ }
+ long rSize = remoteFile.length();
+ if (rSize < 0 || rSize != size) {
+ return true;
+ }
+ String ct = remoteFile.getContentType();
+ return ct == null || !ct.equals(contentType);
+ }
+
+
+ public void update(VltEntryInfo base) {
+ setName(((XmlEntryInfo) base).getName());
+ setDate(base.getDate());
+ setMd5(base.getMd5());
+ setContentType(base.getContentType());
+ setSize(base.getSize());
+ }
+
+ public void update(File file, boolean force) throws IOException {
+ if (file.isDirectory()) {
+ dirty = size != 0 && md5 != null && contentType != null;
+ if (dirty) {
+ size = 0;
+ md5 = null;
+ contentType = null;
+ date = file.lastModified();
+ }
+ } else {
+ if (force || file.lastModified() != date || file.length() != size) {
+ size = file.length();
+ md5 = MD5.digest(file);
+ date = file.lastModified();
+ dirty = true;
+ }
+ }
+ }
+
+ public void update(MetaFile file, boolean force) throws IOException {
+ if (force || file.lastModified() > date) {
+ size = file.length();
+ md5 = file.md5();
+ date = file.lastModified();
+ dirty = true;
+ }
+ }
+
+ public boolean isDirectory() {
+ return size == 0 && md5 == null && contentType == null;
+ }
+
+ public boolean isDirty() {
+ return dirty;
+ }
+
+ public boolean isSame(VltEntryInfo base) {
+ return size == base.getSize()
+ && ((md5 == null && base.getMd5() == null)
+ || md5 != null && md5.equals(base.getMd5()));
+ }
+
+ public void write(ContentHandler handler) throws SAXException {
+ AttributesImpl attrs = new AttributesImpl();
+ addAttributes(attrs);
+ handler.startElement("", type.name().toLowerCase(), "", attrs);
+ handler.endElement("", type.name().toLowerCase(), "");
+ dirty = false;
+ }
+
+ protected void addAttributes(AttributesImpl attrs) {
+ if (name != null) {
+ attrs.addAttribute("", AN_NAME, "", "CDATA", name);
+ }
+ if (date > 0) {
+ Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(date);
+ attrs.addAttribute("", AN_DATE, "", "CDATA", ISO8601.format(c));
+ }
+ if (md5 != null) {
+ attrs.addAttribute("", AN_MD5, "", "CDATA", md5.toString());
+ }
+ if (contentType != null) {
+ attrs.addAttribute("", AN_CONTENT_TYPE, "", "CDATA", contentType);
+ }
+ if (size > 0) {
+ attrs.addAttribute("", AN_SIZE, "", "CDATA", String.valueOf(size));
+ }
+ }
+
+ protected static VltEntryInfo load(Element elem)
+ throws VltException {
+ Type type;
+ try {
+ type = Type.valueOf(elem.getNodeName().toUpperCase());
+ } catch (IllegalArgumentException e) {
+ throw new VltException("unknown entry type '" + elem.getNodeName() + "'");
+ }
+ XmlEntryInfo entry = new XmlEntryInfo(type);
+ if (elem.hasAttribute(AN_NAME)) {
+ entry.setName(elem.getAttribute(AN_NAME));
+ }
+ if (elem.hasAttribute(AN_DATE)) {
+ entry.setDate(ISO8601.parse(elem.getAttribute(AN_DATE)).getTime().getTime());
+ }
+ if (elem.hasAttribute(AN_MD5)) {
+ try {
+ entry.setMd5(new MD5(elem.getAttribute(AN_MD5)));
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ if (elem.hasAttribute(AN_CONTENT_TYPE)) {
+ entry.setContentType(elem.getAttribute(AN_CONTENT_TYPE));
+ }
+ if (elem.hasAttribute(AN_SIZE)) {
+ try {
+ entry.setSize(Integer.parseInt(elem.getAttribute(AN_SIZE)));
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ }
+ entry.dirty = false;
+ return entry;
+ }
+
+
+}
\ No newline at end of file