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 2018/07/24 14:32:13 UTC
svn commit: r1836554 [1/2] - in
/jackrabbit/commons/filevault/trunk/vault-core: ./
src/main/java/org/apache/jackrabbit/vault/packaging/impl/
src/main/java/org/apache/jackrabbit/vault/packaging/registry/
src/main/java/org/apache/jackrabbit/vault/packagi...
Author: tripod
Date: Tue Jul 24 14:32:12 2018
New Revision: 1836554
URL: http://svn.apache.org/viewvc?rev=1836554&view=rev
Log:
JCRVLT-180 implement filesystem based persistence layer
Added:
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/AbstractPackageRegistry.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSInstallState.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSPackageRegistry.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSPackageStatus.java
- copied, changed from r1833974, jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/package-info.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSRegisteredPackage.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/InternalPackageRegistry.java
jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestFSInstallState.java
jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestFSPackageRegistry.java
Modified:
jackrabbit/commons/filevault/trunk/vault-core/pom.xml
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/SubPackageExportProcessor.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/ExecutionPlanBuilderImpl.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/PackageTaskImpl.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/package-info.java
jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java
jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestPackageInstall.java
jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestSubPackages.java
Modified: jackrabbit/commons/filevault/trunk/vault-core/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/pom.xml?rev=1836554&r1=1836553&r2=1836554&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/pom.xml (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/pom.xml Tue Jul 24 14:32:12 2018
@@ -148,6 +148,13 @@
<artifactId>jcr</artifactId>
<scope>provided</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>4.3.0</version>
+ <scope>provided</scope>
+ </dependency>
<!-- SLF4j / Log4j -->
<dependency>
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java?rev=1836554&r1=1836553&r2=1836554&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java Tue Jul 24 14:32:12 2018
@@ -58,6 +58,7 @@ import org.apache.jackrabbit.vault.packa
import org.apache.jackrabbit.vault.packaging.VaultPackage;
import org.apache.jackrabbit.vault.packaging.events.PackageEvent;
import org.apache.jackrabbit.vault.packaging.events.impl.PackageEventDispatcher;
+import org.apache.jackrabbit.vault.packaging.registry.PackageRegistry;
import org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry;
import org.apache.jackrabbit.vault.packaging.registry.impl.JcrRegisteredPackage;
import org.apache.jackrabbit.vault.util.JcrConstants;
@@ -102,7 +103,11 @@ public class JcrPackageManagerImpl exten
return new RepositoryException(e);
}
- public JcrPackageRegistry getRegistry() {
+ public PackageRegistry getRegistry() {
+ return registry;
+ }
+
+ public JcrPackageRegistry getInternalRegistry() {
return registry;
}
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/SubPackageExportProcessor.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/SubPackageExportProcessor.java?rev=1836554&r1=1836553&r2=1836554&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/SubPackageExportProcessor.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/SubPackageExportProcessor.java Tue Jul 24 14:32:12 2018
@@ -73,7 +73,7 @@ public class SubPackageExportProcessor i
if (Text.isDescendantOrEqual(DEFAULT_PACKAGE_ROOT_PATH, nodePath)) {
continue;
}
- String etcPath = DEFAULT_PACKAGE_ROOT_PATH + mgr.getRegistry().getRelativeInstallationPath(pkg.getKey()) + ".zip";
+ String etcPath = DEFAULT_PACKAGE_ROOT_PATH + mgr.getInternalRegistry().getRelativeInstallationPath(pkg.getKey()) + ".zip";
etcPath = Text.getRelativeParent(etcPath, 1);
// define a workspace filter for the package at the real location
@@ -116,7 +116,7 @@ public class SubPackageExportProcessor i
}
}
// now also get the packages from the primary root
- WorkspaceFilter filter = originalFilter.translate(new SimplePathMapping(DEFAULT_PACKAGE_ROOT_PATH, mgr.getRegistry().getPackRootPaths()[0]));
+ WorkspaceFilter filter = originalFilter.translate(new SimplePathMapping(DEFAULT_PACKAGE_ROOT_PATH, mgr.getInternalRegistry().getPackRootPaths()[0]));
for (JcrPackage pkg: mgr.listPackages(filter)) {
if (pkg.isValid() && pkg.getSize() > 0) {
subPackages.put(pkg.getDefinition().getId(), pkg.getNode().getPath());
@@ -128,7 +128,7 @@ public class SubPackageExportProcessor i
Iterator<PathFilterSet> iter = newFilter.getFilterSets().iterator();
while (iter.hasNext()) {
PathFilterSet set = iter.next();
- for (String root : mgr.getRegistry().getPackRootPaths()) {
+ for (String root : mgr.getInternalRegistry().getPackRootPaths()) {
if (Text.isDescendantOrEqual(root, set.getRoot())) {
iter.remove();
break;
@@ -138,7 +138,7 @@ public class SubPackageExportProcessor i
iter = newFilter.getPropertyFilterSets().iterator();
while (iter.hasNext()) {
PathFilterSet set = iter.next();
- for (String root : mgr.getRegistry().getPackRootPaths()) {
+ for (String root : mgr.getInternalRegistry().getPackRootPaths()) {
if (Text.isDescendantOrEqual(root, set.getRoot())) {
iter.remove();
break;
@@ -148,7 +148,7 @@ public class SubPackageExportProcessor i
// re-add all the packages in /etc/packages
for (Map.Entry<PackageId, String> pkg : subPackages.entrySet()) {
- String path = DEFAULT_PACKAGE_ROOT_PATH + mgr.getRegistry().getRelativeInstallationPath(pkg.getKey()) + ".zip";
+ String path = DEFAULT_PACKAGE_ROOT_PATH + mgr.getInternalRegistry().getRelativeInstallationPath(pkg.getKey()) + ".zip";
newFilter.add(new PathFilterSet(path));
}
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/AbstractPackageRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/AbstractPackageRegistry.java?rev=1836554&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/AbstractPackageRegistry.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/AbstractPackageRegistry.java Tue Jul 24 14:32:12 2018
@@ -0,0 +1,218 @@
+/*
+ * 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.packaging.registry.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.fs.io.ImportOptions;
+import org.apache.jackrabbit.vault.packaging.Dependency;
+import org.apache.jackrabbit.vault.packaging.NoSuchPackageException;
+import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.apache.jackrabbit.vault.packaging.PackageExistsException;
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.registry.DependencyReport;
+import org.apache.jackrabbit.vault.packaging.registry.ExecutionPlanBuilder;
+import org.apache.jackrabbit.vault.packaging.registry.PackageRegistry;
+import org.apache.jackrabbit.vault.packaging.registry.RegisteredPackage;
+
+/**
+ * Abstraction for shared methods of PackageRegistry & InternalPackageRegistry implementations
+ */
+public abstract class AbstractPackageRegistry implements PackageRegistry, InternalPackageRegistry {
+
+ /**
+ * default root path for packages
+ */
+ public static final String DEFAULT_PACKAGE_ROOT_PATH = "/etc/packages";
+
+ /**
+ * Archive root path for packages
+ */
+ public final static String ARCHIVE_PACKAGE_ROOT_PATH = "/jcr_root" + DEFAULT_PACKAGE_ROOT_PATH;
+
+ /**
+ * default root path prefix for packages
+ */
+ public static final String DEFAULT_PACKAGE_ROOT_PATH_PREFIX = DEFAULT_PACKAGE_ROOT_PATH + "/";
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract void installPackage(Session session, RegisteredPackage pkg, ImportOptions opts, boolean extract)
+ throws IOException, PackageException;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract void uninstallPackage(Session session, RegisteredPackage pkg, ImportOptions opts)
+ throws IOException, PackageException;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract boolean contains(PackageId id) throws IOException;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract Set<PackageId> packages() throws IOException;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract RegisteredPackage open(PackageId id) throws IOException;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract PackageId register(InputStream in, boolean replace) throws IOException, PackageExistsException;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract PackageId register(File file, boolean replace) throws IOException, PackageExistsException;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract PackageId registerExternal(File file, boolean replace) throws IOException, PackageExistsException;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract void remove(PackageId id) throws IOException, NoSuchPackageException;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ @Override
+ public DependencyReport analyzeDependencies(@Nonnull PackageId id, boolean onlyInstalled) throws IOException, NoSuchPackageException {
+ List<Dependency> unresolved = new LinkedList<Dependency>();
+ List<PackageId> resolved = new LinkedList<PackageId>();
+ try (RegisteredPackage pkg = open(id)) {
+ if (pkg == null) {
+ throw new NoSuchPackageException().setId(id);
+ }
+ //noinspection resource
+ for (Dependency dep : pkg.getPackage().getDependencies()) {
+ PackageId resolvedId = resolve(dep, onlyInstalled);
+ if (resolvedId == null) {
+ unresolved.add(dep);
+ } else {
+ resolved.add(resolvedId);
+ }
+ }
+ }
+
+ return new DependencyReportImpl(id, unresolved.toArray(new Dependency[unresolved.size()]),
+ resolved.toArray(new PackageId[resolved.size()])
+ );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public abstract PackageId resolve(Dependency dependency, boolean onlyInstalled) throws IOException;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ @Override
+ public PackageId[] usage(PackageId id) throws IOException {
+ TreeSet<PackageId> usages = new TreeSet<PackageId>();
+ for (PackageId pid : packages()) {
+ try (RegisteredPackage pkg = open(pid)) {
+ if (pkg == null || !pkg.isInstalled()) {
+ continue;
+ }
+ // noinspection resource
+ for (Dependency dep : pkg.getPackage().getDependencies()) {
+ if (dep.matches(id)) {
+ usages.add(pid);
+ break;
+ }
+ }
+ }
+ }
+ return usages.toArray(new PackageId[usages.size()]);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ @Override
+ public ExecutionPlanBuilder createExecutionPlan() {
+ return new ExecutionPlanBuilderImpl(this);
+ }
+
+ /**
+ * Returns the relative path of this package. please note that since 2.3 this also
+ * includes the version, but never the extension (.zip).
+ *
+ * @param id the package id
+ * @return the relative path of this package
+ * @since 2.2
+ */
+ public String getRelativeInstallationPath(PackageId id) {
+ StringBuilder b = new StringBuilder("/");
+ if (id.getGroup().length() > 0) {
+ b.append(id.getGroup());
+ b.append("/");
+ }
+ b.append(id.getName());
+ String v = id.getVersion().toString();
+ if (v.length() > 0) {
+ b.append("-").append(v);
+ }
+ return b.toString();
+ }
+
+
+ /**
+ * Creates a random package id for packages that lack one.
+ *
+ * @return a random package id.
+ */
+ protected static PackageId createRandomPid() {
+ return new PackageId("temporary", "pack_" + UUID.randomUUID().toString(), (String) null);
+ }
+
+
+}
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/ExecutionPlanBuilderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/ExecutionPlanBuilderImpl.java?rev=1836554&r1=1836553&r2=1836554&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/ExecutionPlanBuilderImpl.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/ExecutionPlanBuilderImpl.java Tue Jul 24 14:32:12 2018
@@ -44,6 +44,7 @@ import org.apache.jackrabbit.vault.packa
import org.apache.jackrabbit.vault.packaging.registry.DependencyReport;
import org.apache.jackrabbit.vault.packaging.registry.ExecutionPlan;
import org.apache.jackrabbit.vault.packaging.registry.ExecutionPlanBuilder;
+import org.apache.jackrabbit.vault.packaging.registry.PackageRegistry;
import org.apache.jackrabbit.vault.packaging.registry.PackageTask;
import org.apache.jackrabbit.vault.packaging.registry.PackageTaskBuilder;
import org.apache.jackrabbit.vault.packaging.registry.RegisteredPackage;
@@ -81,7 +82,7 @@ public class ExecutionPlanBuilderImpl im
private final List<TaskBuilder> tasks = new LinkedList<TaskBuilder>();
- private final JcrPackageRegistry registry;
+ private final PackageRegistry registry;
private Session session;
@@ -89,7 +90,7 @@ public class ExecutionPlanBuilderImpl im
private ExecutionPlanImpl plan;
- ExecutionPlanBuilderImpl(JcrPackageRegistry registry) {
+ ExecutionPlanBuilderImpl(PackageRegistry registry) {
this.registry = registry;
}
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSInstallState.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSInstallState.java?rev=1836554&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSInstallState.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSInstallState.java Tue Jul 24 14:32:12 2018
@@ -0,0 +1,285 @@
+/*
+ * 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.packaging.registry.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.vault.packaging.Dependency;
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.SubPackageHandling;
+import org.apache.jackrabbit.vault.util.RejectingEntityResolver;
+import org.apache.jackrabbit.vault.util.xml.serialize.OutputFormat;
+import org.apache.jackrabbit.vault.util.xml.serialize.XMLSerializer;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * Internal (immutable) State object to cache and pass the relevant metadata around.
+ */
+public class FSInstallState {
+
+ private static final String TAG_REGISTRY_METADATA = "registryMetadata";
+
+ private static final String ATTR_PACKAGE_ID = "packageid";
+
+ private static final String ATTR_FILE_PATH = "filepath";
+
+ private static final String ATTR_PACKAGE_STATUS = "packagestatus";
+
+ private static final String ATTR_EXTERNAL = "external";
+
+ private static final String TAG_DEPENDENCY = "dependency";
+
+ private static final String TAG_SUBPACKAGE = "subpackage";
+
+ private static final String ATTR_INSTALLATION_TIME = "installtime";
+
+ private static final String ATTR_SUBPACKAGE_HANDLING_OPTION = "sphoption";
+
+ private final PackageId packageId;
+ private final FSPackageStatus status;
+ private Path filePath;
+ private boolean external;
+ private Set<Dependency> dependencies = Collections.emptySet();
+ private Map<PackageId, SubPackageHandling.Option> subPackages = Collections.emptyMap();
+ private Long installTime;
+
+ public FSInstallState(@Nonnull PackageId pid, @Nonnull FSPackageStatus status) {
+ this.packageId = pid;
+ this.status = status;
+ }
+
+ public FSInstallState withFilePath(Path filePath) {
+ this.filePath = filePath;
+ return this;
+ }
+
+ public FSInstallState withExternal(boolean external) {
+ this.external = external;
+ return this;
+ }
+
+ public FSInstallState withDependencies(Set<Dependency> dependencies) {
+ this.dependencies = dependencies == null
+ ? Collections.<Dependency>emptySet()
+ : Collections.unmodifiableSet(dependencies);
+ return this;
+ }
+
+ public FSInstallState withSubPackages(Map<PackageId, SubPackageHandling.Option> subPackages) {
+ this.subPackages = subPackages == null
+ ? Collections.<PackageId, SubPackageHandling.Option>emptyMap()
+ : Collections.unmodifiableMap(subPackages);
+ return this;
+ }
+
+ public FSInstallState withInstallTime(Long installTime) {
+ this.installTime = installTime;
+ return this;
+ }
+
+ /**
+ * Parses {@code InstallState} from metafile.
+ *
+ * @param metaFile The meta file.
+ * @return Install state or null if file is not metafile format
+ *
+ * @throws IOException in case root tag is correct but structure not parsable as expected
+ */
+ @Nullable
+ public static FSInstallState fromFile(File metaFile) throws IOException {
+ if (!metaFile.exists()) {
+ return null;
+ }
+ try (InputStream in = FileUtils.openInputStream(metaFile)) {
+ return fromStream(in, metaFile.getPath());
+ }
+ }
+
+ /**
+ * Parses {@code InstallState} from metafile.
+ *
+ * @param in The input stream
+ * @param systemId the id of the stream
+ * @return Install state or null if file is not metafile format
+ *
+ * @throws IOException in case root tag is correct but structure not parsable as expected
+ */
+ @Nullable
+ public static FSInstallState fromStream(InputStream in, String systemId) throws IOException {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ builder.setEntityResolver(new RejectingEntityResolver());
+ Document document = builder.parse(in, systemId);
+ Element doc = document.getDocumentElement();
+ if (!TAG_REGISTRY_METADATA.equals(doc.getNodeName())) {
+ return null;
+ }
+ String packageId = doc.getAttribute(ATTR_PACKAGE_ID);
+ Path filePath = Paths.get(doc.getAttribute(ATTR_FILE_PATH));
+ Long installTime = null;
+ if (doc.hasAttribute(ATTR_INSTALLATION_TIME)) {
+ installTime = Long.valueOf(doc.getAttribute(ATTR_INSTALLATION_TIME));
+ }
+ boolean external = Boolean.parseBoolean(doc.getAttribute(ATTR_EXTERNAL));
+ FSPackageStatus status = FSPackageStatus.valueOf(doc.getAttribute(ATTR_PACKAGE_STATUS).toUpperCase());
+ NodeList nl = doc.getChildNodes();
+ Set<Dependency> dependencies = new HashSet<>();
+ Map<PackageId, SubPackageHandling.Option> subPackages = new HashMap<>();
+ for (int i = 0; i < nl.getLength(); i++) {
+ Node child = nl.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ String childName = child.getNodeName();
+ if (TAG_DEPENDENCY.equals(childName)) {
+ dependencies.add(readDependency((Element) child));
+ } else if (TAG_SUBPACKAGE.equals(childName)) {
+ subPackages.put(readPackageId((Element) child), readSubPackgeHandlingOption((Element) child));
+ } else {
+ throw new IOException("<" + TAG_DEPENDENCY + "> or <" + TAG_SUBPACKAGE + "> expected.");
+ }
+ }
+ }
+ return new FSInstallState(PackageId.fromString(packageId), status)
+ .withFilePath(filePath)
+ .withExternal(external)
+ .withDependencies(dependencies)
+ .withSubPackages(subPackages)
+ .withInstallTime(installTime);
+ } catch (ParserConfigurationException e) {
+ throw new IOException("Unable to create configuration XML parser", e);
+ } catch (SAXException e) {
+ throw new IOException("Configuration file syntax error.", e);
+ }
+ }
+
+ private static Dependency readDependency(Element child) {
+ return Dependency.fromString(child.getAttribute(ATTR_PACKAGE_ID));
+ }
+
+ private static SubPackageHandling.Option readSubPackgeHandlingOption(Element child) {
+ return SubPackageHandling.Option.valueOf(child.getAttribute(ATTR_SUBPACKAGE_HANDLING_OPTION));
+ }
+
+ private static PackageId readPackageId(Element child) {
+ return PackageId.fromString(child.getAttribute(ATTR_PACKAGE_ID));
+ }
+
+
+ /**
+ * Persists the installState to a metadatafile
+ * @param file The files to save the state to
+ * @throws IOException if an error occurs.
+ */
+ public void save(File file) throws IOException {
+ try (OutputStream out = FileUtils.openOutputStream(file)) {
+ save(out);
+ }
+ }
+
+ /**
+ * Persists the installState to a metadatafile
+ * @param out Outputsteam to write to.
+ * @throws IOException if an error occurs.
+ */
+ public void save(OutputStream out) throws IOException {
+ try {
+ XMLSerializer ser = new XMLSerializer(out, new OutputFormat("xml", "UTF-8", true));
+ ser.startDocument();
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute(null, null, ATTR_PACKAGE_ID, "CDATA", packageId.toString());
+ if (installTime != null) {
+ attrs.addAttribute(null, null, ATTR_INSTALLATION_TIME, "CDATA", Long.toString(installTime));
+ }
+ attrs.addAttribute(null, null, ATTR_FILE_PATH, "CDATA", filePath.toString());
+ attrs.addAttribute(null, null, ATTR_EXTERNAL, "CDATA", Boolean.toString(external));
+ attrs.addAttribute(null, null, ATTR_PACKAGE_STATUS, "CDATA", status.name().toLowerCase());
+ ser.startElement(null, null, TAG_REGISTRY_METADATA, attrs);
+ if (dependencies != null) {
+ for (Dependency dependency : dependencies) {
+ attrs = new AttributesImpl();
+ attrs.addAttribute(null, null, ATTR_PACKAGE_ID, "CDATA", dependency.toString());
+ ser.startElement(null, null, TAG_DEPENDENCY, attrs);
+ ser.endElement(TAG_DEPENDENCY);
+ }
+ }
+ if (subPackages != null) {
+ for (PackageId subPackId : subPackages.keySet()) {
+ attrs = new AttributesImpl();
+ attrs.addAttribute(null, null, ATTR_PACKAGE_ID, "CDATA", subPackId.toString());
+ attrs.addAttribute(null, null, ATTR_SUBPACKAGE_HANDLING_OPTION, "CDATA", subPackages.get(subPackId).toString());
+ ser.startElement(null, null, TAG_SUBPACKAGE, attrs);
+ ser.endElement(TAG_SUBPACKAGE);
+ }
+ }
+ ser.endElement(TAG_REGISTRY_METADATA);
+ ser.endDocument();
+ } catch (SAXException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public Long getInstallationTime() {
+ return installTime;
+ }
+
+ public Map<PackageId, SubPackageHandling.Option> getSubPackages() {
+ return subPackages;
+ }
+
+ public PackageId getPackageId() {
+ return packageId;
+ }
+
+ public Path getFilePath() {
+ return filePath;
+ }
+
+ public boolean isExternal() {
+ return external;
+ }
+
+ public FSPackageStatus getStatus() {
+ return status;
+ }
+
+ public Set<Dependency> getDependencies() {
+ return dependencies;
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSPackageRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSPackageRegistry.java?rev=1836554&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSPackageRegistry.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSPackageRegistry.java Tue Jul 24 14:32:12 2018
@@ -0,0 +1,712 @@
+/*
+ * 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.packaging.registry.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
+import org.apache.jackrabbit.vault.fs.config.MetaInf;
+import org.apache.jackrabbit.vault.fs.io.Archive;
+import org.apache.jackrabbit.vault.fs.io.ImportOptions;
+import org.apache.jackrabbit.vault.fs.io.MemoryArchive;
+import org.apache.jackrabbit.vault.packaging.Dependency;
+import org.apache.jackrabbit.vault.packaging.NoSuchPackageException;
+import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.apache.jackrabbit.vault.packaging.PackageExistsException;
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.SubPackageHandling;
+import org.apache.jackrabbit.vault.packaging.VaultPackage;
+import org.apache.jackrabbit.vault.packaging.events.PackageEvent;
+import org.apache.jackrabbit.vault.packaging.events.PackageEvent.Type;
+import org.apache.jackrabbit.vault.packaging.events.impl.PackageEventDispatcher;
+import org.apache.jackrabbit.vault.packaging.impl.PackagePropertiesImpl;
+import org.apache.jackrabbit.vault.packaging.impl.ZipVaultPackage;
+import org.apache.jackrabbit.vault.packaging.registry.DependencyReport;
+import org.apache.jackrabbit.vault.packaging.registry.PackageRegistry;
+import org.apache.jackrabbit.vault.packaging.registry.RegisteredPackage;
+import org.apache.jackrabbit.vault.util.InputStreamPump;
+import org.apache.jackrabbit.vault.util.PlatformNameFormat;
+import org.apache.jackrabbit.vault.util.Text;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * FileSystem based registry not depending on a JCR Session. All metadata is stored in Filesystem and can be prepared and used without a running JCR repository
+ * Only methods to install or uninstall packages require an active {@code Session} object of running jcr instance to perform the actual installation tasks
+ */
+@Component(
+ service = PackageRegistry.class,
+ configurationPolicy = ConfigurationPolicy.REQUIRE,
+ property = {"service.vendor=The Apache Software Foundation"}
+)
+@Designate(ocd = FSPackageRegistry.Config.class)
+public class FSPackageRegistry extends AbstractPackageRegistry {
+
+ private static final String REPOSITORY_HOME = "repository.home";
+
+ /**
+ * default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(FSPackageRegistry.class);
+
+ /**
+ * Suffixes for metadata files
+ */
+ private final String[] META_SUFFIXES = {"xml"};
+
+ private Map<PackageId, FSInstallState> stateCache = new ConcurrentHashMap<>();
+
+ /**
+ * Contains a map of all filesystem paths to package IDs
+ */
+ private Map<Path, PackageId> pathIdMapping = new ConcurrentHashMap<>();
+
+
+ private boolean packagesInitializied = false;
+
+ @Reference
+ private PackageEventDispatcher dispatcher;
+
+ private File homeDir;
+
+ private File getHomeDir() {
+ return homeDir;
+ }
+
+ /**
+ * Creates a new FSPackageRegistry based on the given home directory.
+ *
+ * @param homeDir the directory in which packages and their metadata is stored
+ * @throws IOException If an I/O error occurs.
+ */
+ public FSPackageRegistry(@Nonnull File homeDir) throws IOException {
+ this.homeDir = homeDir;
+ loadPackageCache();
+ }
+
+ /**
+ * Deafult constructor for OSGi initialization (homeDir defined via activator)
+ */
+ public FSPackageRegistry() {
+ }
+
+
+ @ObjectClassDefinition(
+ name = "Apache Jackrabbit FS Package Registry Service"
+ )
+ @interface Config {
+
+ @AttributeDefinition
+ String homePath() default "packageregistry";
+ }
+
+ @Activate
+ private void activate(BundleContext context, Config config) throws IOException {
+ String repoHome = context.getProperty(REPOSITORY_HOME);
+ if (repoHome == null) {
+ this.homeDir = context.getDataFile(config.homePath());
+ } else {
+ this.homeDir = new File(repoHome + "/" + config.homePath());
+ if (!homeDir.exists()) {
+ homeDir.mkdirs();
+ }
+ }
+ loadPackageCache();
+ log.info("Jackrabbit Filevault FS Package Registry initialized with home location {}", this.homeDir.getPath());
+ }
+
+ /**
+ * Sets the event dispatcher
+ *
+ * @param dispatcher the dispatcher.
+ */
+ public void setDispatcher(@Nullable PackageEventDispatcher dispatcher) {
+ this.dispatcher = dispatcher;
+ }
+
+ /**
+ * Dispatches a package event using the configured dispatcher.
+ *
+ * @param type event type
+ * @param id package id
+ * @param related related packages
+ */
+ public void dispatch(@Nonnull PackageEvent.Type type, @Nonnull PackageId id, @Nullable PackageId[] related) {
+ if (dispatcher == null) {
+ return;
+ }
+ dispatcher.dispatch(type, id, related);
+ }
+
+ @Nullable
+ @Override
+ public RegisteredPackage open(@Nonnull PackageId id) throws IOException {
+ try {
+ File pkg = getPackageFile(id);
+ return pkg != null && pkg.exists() ? new FSRegisteredPackage(this, open(pkg)) : null;
+ } catch (RepositoryException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public boolean contains(@Nonnull PackageId id) throws IOException {
+ return stateCache.containsKey(id);
+ }
+
+ @Nullable
+ private File getPackageFile(@Nonnull PackageId id) {
+ try {
+ FSInstallState state = getInstallState(id);
+ if (FSPackageStatus.NOTREGISTERED == state.getStatus()) {
+ return buildPackageFile(id);
+ } else {
+ return state.getFilePath().toFile();
+ }
+ } catch (IOException e) {
+ log.error("Couldn't get install state of packageId {}", id, e);
+ }
+ return null;
+ }
+
+ private File buildPackageFile(@Nonnull PackageId id) {
+ String path = getInstallationPath(id);
+ return new File(getHomeDir(), path + ".zip");
+ }
+
+ /**
+ * Returns the meta data file of the package with the given Id.
+ *
+ * @param id The package Id.
+ * @return the meta data file.
+ */
+ @Nonnull
+ private File getPackageMetaDataFile(@Nonnull PackageId id) {
+ final String path = getInstallationPath(id);
+ return new File(getHomeDir(), path + ".xml");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public VaultPackage open(File pkg) throws RepositoryException {
+ try {
+ return new ZipVaultPackage(pkg, false, true);
+ } catch (IOException e) {
+ log.error("Cloud not open file {} as ZipVaultPackage.", pkg.getPath(), e);
+ return null;
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ @Override
+ public DependencyReport analyzeDependencies(@Nonnull PackageId id, boolean onlyInstalled) throws IOException, NoSuchPackageException {
+ List<Dependency> unresolved = new LinkedList<>();
+ List<PackageId> resolved = new LinkedList<>();
+ FSInstallState state = getInstallState(id);
+ if (FSPackageStatus.NOTREGISTERED == state.getStatus()) {
+ throw new NoSuchPackageException().setId(id);
+ }
+
+ // Make sure that also dependencies of contained packages are considered as packages will be installed in a joined sequence.
+ Set<Dependency> allDependencies = new HashSet<>();
+ allDependencies.addAll(state.getDependencies());
+ for (PackageId subId : state.getSubPackages().keySet()) {
+ FSInstallState subState = getInstallState(subId);
+ allDependencies.addAll(subState.getDependencies());
+ }
+
+ for (Dependency dep : allDependencies) {
+ PackageId resolvedId = resolve(dep, onlyInstalled);
+ if (resolvedId == null) {
+ unresolved.add(dep);
+ } else {
+ resolved.add(resolvedId);
+ }
+ }
+
+ return new DependencyReportImpl(id, unresolved.toArray(new Dependency[unresolved.size()]),
+ resolved.toArray(new PackageId[resolved.size()])
+ );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public PackageId resolve(Dependency dependency, boolean onlyInstalled) throws IOException {
+ PackageId bestId = null;
+ for (PackageId id : packages()) {
+ if (!onlyInstalled || isInstalled(id)) {
+ if (dependency.matches(id)) {
+ if (bestId == null || id.getVersion().compareTo(bestId.getVersion()) > 0) {
+ bestId = id;
+ }
+ }
+ }
+ }
+ return bestId;
+ }
+
+ /**
+ * Returns {@code true} when state {@link FSPackageStatus#EXTRACTED} is recorded for given {@code PackageId}
+ *
+ * @param id PackageId of the package to test.
+ * @return {@code true} if package is in state {@link FSPackageStatus#EXTRACTED}
+ *
+ * @throws IOException If an I/O error occurs.
+ */
+ boolean isInstalled(PackageId id) throws IOException {
+ FSPackageStatus status = getInstallState(id).getStatus();
+ return FSPackageStatus.EXTRACTED == status;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ @Override
+ public PackageId register(@Nonnull InputStream in, boolean replace) throws IOException, PackageExistsException {
+ return register(in, replace, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ private PackageId register(@Nonnull InputStream in, boolean replace, Dependency autoDependency) throws IOException, PackageExistsException {
+ ZipVaultPackage pkg = upload(in, replace);
+
+ Map<PackageId, SubPackageHandling.Option> subpackages = registerSubPackages(pkg, replace);
+ File pkgFile = buildPackageFile(pkg.getId());
+ HashSet<Dependency> dependencies = new HashSet<>();
+ dependencies.addAll(Arrays.asList(pkg.getDependencies()));
+ if (autoDependency != null) {
+ dependencies.add(autoDependency);
+ }
+ setInstallState(pkg.getId(), FSPackageStatus.REGISTERED, pkgFile.toPath(), false, dependencies, subpackages,
+ null);
+ return pkg.getId();
+ }
+
+ /**
+ * Registers subpackages in registry
+ *
+ * @param pkg The package to regist
+ * @param replace {@code true} to replace
+ * @return {@code Map} of {@code PackageId}s along with the corresponding {@code SubPackageHandling.Option} registered from a given {@code VaultPackage}
+ *
+ * @throws IOException
+ * @throws PackageExistsException
+ */
+ private Map<PackageId, SubPackageHandling.Option> registerSubPackages(VaultPackage pkg, boolean replace)
+ throws IOException, PackageExistsException {
+ Map<PackageId, SubPackageHandling.Option> subpackages = new HashMap<>();
+
+ Archive.Entry packagesRoot = pkg.getArchive().getEntry(ARCHIVE_PACKAGE_ROOT_PATH);
+ if (packagesRoot != null) {
+ // As for JcrPackageImpl subpackages need to get an implicit autoDependency to the parent in case they have own content
+ boolean hasOwnContent = false;
+ for (PathFilterSet root : pkg.getArchive().getMetaInf().getFilter().getFilterSets()) {
+ // todo: find better way to detect subpackages
+ if (!Text.isDescendantOrEqual(DEFAULT_PACKAGE_ROOT_PATH, root.getRoot())) {
+ log.debug(
+ "Package {}: contains content outside /etc/packages. Sub packages will have a dependency to it",
+ pkg.getId());
+ hasOwnContent = true;
+ }
+ }
+ Dependency autoDependency = hasOwnContent ? new Dependency(pkg.getId()) : null;
+ registerSubPackages(pkg, packagesRoot, DEFAULT_PACKAGE_ROOT_PATH, replace, subpackages, autoDependency);
+ dispatch(Type.EXTRACT_SUB_PACKAGES, pkg.getId(), subpackages.keySet().toArray(new PackageId[subpackages.size()]));
+ }
+ return subpackages;
+ }
+
+ /**
+ * Parses given {@link Archive.Entry} for .jar & .zip binaries and tries to register given subpackage.
+ *
+ * @param vltPkg
+ * @param directory
+ * @param parentPath
+ * @param replace
+ * @param subpackages
+ * @throws IOException
+ * @throws PackageExistsException
+ */
+ private void registerSubPackages(VaultPackage vltPkg, Archive.Entry directory, String parentPath, boolean replace, Map<PackageId, SubPackageHandling.Option> subpackages, Dependency autoDependency)
+ throws IOException, PackageExistsException {
+ Collection<? extends Archive.Entry> files = directory.getChildren();
+
+ for (Archive.Entry file : files) {
+ String fileName = file.getName();
+ String repoName = PlatformNameFormat.getRepositoryName(fileName);
+ String repoPath = parentPath + "/" + repoName;
+ if (file.isDirectory()) {
+ registerSubPackages(vltPkg, file, repoPath, replace, subpackages, autoDependency);
+ } else {
+ if (repoPath.startsWith(DEFAULT_PACKAGE_ROOT_PATH_PREFIX) && (repoPath.endsWith(".jar") || repoPath.endsWith(".zip"))) {
+ try (InputStream in = vltPkg.getArchive().openInputStream(file)) {
+ if (in == null) {
+ throw new IOException("Unable to open archive input stream of " + file);
+ }
+ PackageId id = register(in, replace);
+ SubPackageHandling.Option option = vltPkg.getSubPackageHandling().getOption(id);
+ subpackages.put(id, option);
+ } catch (PackageExistsException e) {
+ log.info("Subpackage already registered, skipping subpackage extraction.");
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ZipVaultPackage upload(InputStream in, boolean replace)
+ throws IOException, PackageExistsException {
+
+ MemoryArchive archive = new MemoryArchive(false);
+ File tempFile = File.createTempFile("upload", ".zip");
+
+ try (InputStreamPump pump = new InputStreamPump(in, archive)) {
+ // this will cause the input stream to be consumed and the memory
+ // archive being initialized.
+ try {
+
+ FileUtils.copyInputStreamToFile(pump, tempFile);
+ } catch (Exception e) {
+ String msg = "Stream could be read successfully.";
+ log.error(msg);
+ throw new IOException(msg, e);
+ }
+
+ if (archive.getJcrRoot() == null) {
+ String msg = "Stream is not a content package. Missing 'jcr_root'.";
+ log.error(msg);
+ throw new IOException(msg);
+ }
+
+ final MetaInf inf = archive.getMetaInf();
+ PackagePropertiesImpl props = new PackagePropertiesImpl() {
+ @Override
+ protected Properties getPropertiesMap() {
+ return inf.getProperties();
+ }
+ };
+ PackageId pid = props.getId();
+
+ // invalidate pid if path is unknown
+ if (pid == null) {
+ throw new IllegalArgumentException("Unable to create package. No package pid set.");
+ }
+ if (!pid.isValid()) {
+ throw new IllegalArgumentException("Unable to create package. Illegal package name.");
+ }
+
+ File oldPkgFile = getPackageFile(pid);
+ FSInstallState state = getInstallState(pid);
+
+ if (oldPkgFile != null && oldPkgFile.exists()) {
+ if (replace && !state.isExternal()) {
+ oldPkgFile.delete();
+ } else {
+ throw new PackageExistsException("Package already exists: " + pid).setId(pid);
+ }
+ }
+
+ ZipVaultPackage pkg = new ZipVaultPackage(archive, true);
+ registerSubPackages(pkg, replace);
+ File pkgFile = buildPackageFile(pid);
+ FileUtils.moveFile(tempFile, pkgFile);
+ dispatch(Type.UPLOAD, pid, null);
+ return pkg;
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ @Override
+ public PackageId register(@Nonnull File file, boolean replace) throws IOException, PackageExistsException {
+ ZipVaultPackage pack = new ZipVaultPackage(file, false, true);
+ try {
+ File pkgFile = buildPackageFile(pack.getId());
+ if (pkgFile.exists()) {
+ if (replace) {
+ pkgFile.delete();
+ } else {
+ throw new PackageExistsException("Package already exists: " + pack.getId()).setId(pack.getId());
+ }
+ }
+ Map<PackageId, SubPackageHandling.Option> subpackages = registerSubPackages(pack, replace);
+ FileUtils.copyFile(file, pkgFile);
+ Collection<Dependency> dependencies = Arrays.asList(pack.getDependencies());
+ setInstallState(pack.getId(), FSPackageStatus.REGISTERED, pkgFile.toPath(), false, new HashSet<>(dependencies), subpackages, null);
+ return pack.getId();
+ } finally {
+ if (!pack.isClosed()) {
+ pack.close();
+ }
+ }
+ }
+
+ @Nonnull
+ @Override
+ public PackageId registerExternal(@Nonnull File file, boolean replace) throws IOException, PackageExistsException {
+ if (!replace && pathIdMapping.containsKey(file.getPath())) {
+ throw new PackageExistsException("Package already exists: " + pathIdMapping.get(file.getPath()));
+ }
+ ZipVaultPackage pack = new ZipVaultPackage(file, false, true);
+ try {
+
+ FSInstallState state = getInstallState(pack.getId());
+ if (!(FSPackageStatus.NOTREGISTERED == state.getStatus())) {
+ if (replace) {
+ try {
+ remove(pack.getId());
+ } catch (NoSuchPackageException e) {
+ log.error("Status isn't NOTREGISTERD but no metafile exists to remove", e);
+ }
+ } else {
+ throw new PackageExistsException("Package already exists: " + pack.getId()).setId(pack.getId());
+ }
+ }
+ Map<PackageId, SubPackageHandling.Option> subpackages = registerSubPackages(pack, replace);
+ Collection<Dependency> dependencies = Arrays.asList(pack.getDependencies());
+ setInstallState(pack.getId(), FSPackageStatus.REGISTERED, file.toPath(), true, new HashSet<>(dependencies), subpackages, null);
+ return pack.getId();
+ } finally {
+ if (!pack.isClosed()) {
+ pack.close();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void remove(@Nonnull PackageId id) throws IOException, NoSuchPackageException {
+ FSInstallState state = getInstallState(id);
+ File metaData = getPackageMetaDataFile(id);
+
+ if (!metaData.exists()) {
+ throw new NoSuchPackageException().setId(id);
+ }
+ metaData.delete();
+
+ if (!state.isExternal()) {
+ getPackageFile(id).delete();
+ }
+ updateInstallState(id, FSPackageStatus.NOTREGISTERED);
+ dispatch(PackageEvent.Type.REMOVE, id, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Nonnull
+ @Override
+ public Set<PackageId> packages() throws IOException {
+ return packagesInitializied ? stateCache.keySet() : loadPackageCache();
+ }
+
+ /**
+ * Loads all state from files persisted in configured homeDir, adds to cache and returns all cached {@code PackageId}s.
+ *
+ * @return {@code Set} of all cached {@code PackageId}s
+ *
+ * @throws IOException If an I/O error occurs
+ */
+ private Set<PackageId> loadPackageCache() throws IOException {
+ Map<PackageId, FSInstallState> cacheEntries = new HashMap<>();
+ Map<Path, PackageId> idMapping = new HashMap<>();
+
+
+ Collection<File> files = FileUtils.listFiles(getHomeDir(), META_SUFFIXES, true);
+ for (File file : files) {
+ FSInstallState state = FSInstallState.fromFile(file);
+ if (state != null) {
+ PackageId id = state.getPackageId();
+ if (id != null) {
+ cacheEntries.put(id, state);
+ idMapping.put(state.getFilePath(), id);
+
+ }
+ }
+ }
+ stateCache.putAll(cacheEntries);
+ pathIdMapping.putAll(idMapping);
+ packagesInitializied = true;
+ return cacheEntries.keySet();
+ }
+
+ /**
+ * Returns the path of this package.this also includes the version, but
+ * never the extension (.zip).
+ *
+ * @param id the package id
+ * @return the path of this package
+ */
+ public String getInstallationPath(PackageId id) {
+ return getRelativeInstallationPath(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void installPackage(@Nonnull Session session, @Nonnull RegisteredPackage pkg, @Nonnull ImportOptions opts,
+ boolean extract) throws IOException, PackageException {
+
+ // For now FS based persistence only supports extraction but no reversible installation
+ if (!extract) {
+ String msg = "Only extraction supported by FS based registry";
+ log.error(msg);
+ throw new PackageException(msg);
+ }
+ try (VaultPackage vltPkg = pkg.getPackage()) {
+ vltPkg.extract(session, opts);
+ dispatch(PackageEvent.Type.EXTRACT, pkg.getId(), null);
+ updateInstallState(vltPkg.getId(), FSPackageStatus.EXTRACTED);
+
+ } catch (RepositoryException e) {
+ throw new IOException(e);
+ }
+ }
+
+ /**
+ * Uninstallation not supported for FS based PackageRegistry
+ */
+ @Override
+ public void uninstallPackage(@Nonnull Session session, @Nonnull RegisteredPackage pkg, @Nonnull ImportOptions opts) throws IOException, PackageException {
+ String msg = "Uninstallation not supported by FS based registry";
+ log.error(msg);
+ throw new PackageException(msg);
+ }
+
+ /**
+ * Shortcut to just change the status of a package - implicitly sets the installtime when switching to EXTRACTED
+ *
+ * @param pid PackageId of the package to update
+ * @param targetStatus Status to update
+ * @throws IOException If an I/O error occurs.
+ */
+ private void updateInstallState(PackageId pid, FSPackageStatus targetStatus) throws IOException {
+ FSInstallState state = getInstallState(pid);
+ Long installTime = state.getInstallationTime();
+ if (FSPackageStatus.EXTRACTED == targetStatus) {
+ installTime = Calendar.getInstance().getTimeInMillis();
+ }
+ setInstallState(pid, targetStatus, state.getFilePath(), state.isExternal(), state.getDependencies(), state.getSubPackages(), installTime);
+ }
+
+ /**
+ * Persists the installState to a metadatafile and adds current state to cache
+ *
+ * @param pid
+ * @param targetStatus
+ * @param filePath
+ * @param external
+ * @param dependencies
+ * @param subPackages
+ * @param installTimeStamp
+ * @throws IOException
+ */
+ private void setInstallState(@Nonnull PackageId pid, @Nonnull FSPackageStatus targetStatus, @Nonnull Path filePath, @Nonnull boolean external, @Nullable Set<Dependency> dependencies, @Nullable Map<PackageId, SubPackageHandling.Option> subPackages, @Nullable Long installTimeStamp) throws IOException {
+ File metaData = getPackageMetaDataFile(pid);
+
+ if (targetStatus == FSPackageStatus.NOTREGISTERED) {
+ pathIdMapping.remove(stateCache.get(pid).getFilePath());
+ metaData.delete();
+ stateCache.remove(pid);
+ } else {
+ FSInstallState state = new FSInstallState(pid, targetStatus)
+ .withFilePath(filePath)
+ .withDependencies(dependencies)
+ .withSubPackages(subPackages)
+ .withInstallTime(installTimeStamp)
+ .withExternal(external);
+ state.save(metaData);
+ stateCache.put(pid, state);
+ pathIdMapping.put(state.getFilePath(), pid);
+ }
+ }
+
+ /**
+ * Retrieves {@code InstallState} from cache, falls back to reading from metafile and returns state for {@code FSPackageStatus.NOTREGISTERED} in case not found.
+ *
+ * @param pid the PackageId of the package to retrieve the install state from.
+ * @return {@code InstallState} found for given {@code PackageId} or a fresh one with status {@code FSPackageStatus.NOTREGISTERED}
+ *
+ * @throws IOException if an I/O error occurs.
+ */
+ @Nonnull
+ public FSInstallState getInstallState(PackageId pid) throws IOException {
+ if (stateCache.containsKey(pid)) {
+ return stateCache.get(pid);
+ } else {
+ File metaFile = getPackageMetaDataFile(pid);
+ FSInstallState state = FSInstallState.fromFile(metaFile);
+ if (state != null) {
+ //theoretical file - should only be feasible when manipulating on filesystem, writing metafile automatically updates cache
+ stateCache.put(pid, state);
+ pathIdMapping.put(state.getFilePath(), pid);
+ }
+ return state != null ? state : new FSInstallState(pid, FSPackageStatus.NOTREGISTERED);
+ }
+ }
+
+
+}
Copied: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSPackageStatus.java (from r1833974, jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/package-info.java)
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSPackageStatus.java?p2=jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSPackageStatus.java&p1=jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/package-info.java&r1=1833974&r2=1836554&rev=1836554&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/package-info.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSPackageStatus.java Tue Jul 24 14:32:12 2018
@@ -14,5 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@org.osgi.annotation.versioning.Version("1.0.0")
-package org.apache.jackrabbit.vault.packaging.registry;
+package org.apache.jackrabbit.vault.packaging.registry.impl;
+
+/**
+ * Internal Status a package may have in {@code FSPackageRegistry}
+ */
+public enum FSPackageStatus {
+
+ REGISTERED,
+ EXTRACTED,
+ NOTREGISTERED
+
+}
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSRegisteredPackage.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSRegisteredPackage.java?rev=1836554&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSRegisteredPackage.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/FSRegisteredPackage.java Tue Jul 24 14:32:12 2018
@@ -0,0 +1,106 @@
+/*
+ * 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.packaging.registry.impl;
+
+import java.io.IOException;
+import java.util.Calendar;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.VaultPackage;
+import org.apache.jackrabbit.vault.packaging.registry.RegisteredPackage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@code JcrRegisteredPackage}...
+ */
+public class FSRegisteredPackage implements RegisteredPackage {
+
+ /**
+ * default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(FSPackageRegistry.class);
+
+ private VaultPackage vltPkg;
+ private FSPackageRegistry registry;
+
+ public FSRegisteredPackage(FSPackageRegistry registry, VaultPackage vltPkg) throws IOException, RepositoryException {
+ this.vltPkg = vltPkg;
+ this.registry = registry;
+ }
+
+ @Nonnull
+ @Override
+ public PackageId getId() {
+ return vltPkg.getId();
+ }
+
+ @Nonnull
+ @Override
+ public VaultPackage getPackage() throws IOException {
+ return vltPkg;
+ }
+
+ @Override
+ public boolean isInstalled() {
+ try {
+ return registry.isInstalled(getId());
+ } catch (IOException e) {
+ log.error("Packagestate couldn't be read for package {}", getId().toString(), e);
+ return false;
+ }
+ }
+
+ @Override
+ public long getSize() {
+ return vltPkg.getSize();
+ }
+
+ @CheckForNull
+ @Override
+ public Calendar getInstallationTime() {
+ Calendar cal = Calendar.getInstance();
+ Long installTime;
+ try {
+ installTime = registry.getInstallState(getId()).getInstallationTime();
+ if (installTime == null) {
+ cal = null;
+ } else{
+ cal.setTimeInMillis(installTime);
+ }
+ } catch (IOException e) {
+ log.error("Could not read package state for package {}.", getId(), e);
+ cal = null;
+ }
+ return cal;
+ }
+
+ @Override
+ public void close() {
+ vltPkg.close();
+ vltPkg = null;
+ }
+
+ @Override
+ public int compareTo(RegisteredPackage o) {
+ return getId().compareTo(o.getId());
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/InternalPackageRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/InternalPackageRegistry.java?rev=1836554&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/InternalPackageRegistry.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/InternalPackageRegistry.java Tue Jul 24 14:32:12 2018
@@ -0,0 +1,37 @@
+/*
+ * 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.packaging.registry.impl;
+
+import java.io.IOException;
+
+import javax.annotation.Nonnull;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.fs.io.ImportOptions;
+import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.apache.jackrabbit.vault.packaging.registry.PackageRegistry;
+import org.apache.jackrabbit.vault.packaging.registry.RegisteredPackage;
+
+public interface InternalPackageRegistry extends PackageRegistry {
+
+ void installPackage(@Nonnull Session session, @Nonnull RegisteredPackage pkg, @Nonnull ImportOptions opts,
+ boolean extract) throws IOException, PackageException;
+
+ void uninstallPackage(@Nonnull Session session, @Nonnull RegisteredPackage pkg, @Nonnull ImportOptions opts)
+ throws IOException, PackageException;
+
+}
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java?rev=1836554&r1=1836553&r2=1836554&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java Tue Jul 24 14:32:12 2018
@@ -23,8 +23,6 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
-import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
@@ -44,6 +42,7 @@ import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.vault.fs.config.MetaInf;
+import org.apache.jackrabbit.vault.fs.io.ImportOptions;
import org.apache.jackrabbit.vault.fs.io.MemoryArchive;
import org.apache.jackrabbit.vault.fs.spi.CNDReader;
import org.apache.jackrabbit.vault.fs.spi.NodeTypeInstaller;
@@ -77,7 +76,7 @@ import org.slf4j.LoggerFactory;
/**
* {@code JcrPackagePersistence}...
*/
-public class JcrPackageRegistry implements PackageRegistry {
+public class JcrPackageRegistry extends AbstractPackageRegistry {
/**
* default logger
@@ -90,16 +89,6 @@ public class JcrPackageRegistry implemen
private static final String DEFAULT_NODETYPES = "nodetypes.cnd";
/**
- * default root path for packages
- */
- public static final String DEFAULT_PACKAGE_ROOT_PATH = "/etc/packages";
-
- /**
- * default root path prefix for packages
- */
- public static final String DEFAULT_PACKAGE_ROOT_PATH_PREFIX = DEFAULT_PACKAGE_ROOT_PATH + "/";
-
- /**
* suggested folder types
*/
private final static String[] FOLDER_TYPES = {"sling:Folder", "nt:folder", "nt:unstructured", null};
@@ -337,55 +326,6 @@ public class JcrPackageRegistry implemen
}
}
- /**
- * {@inheritDoc}
- */
- @Nonnull
- @Override
- public PackageId[] usage(PackageId id) throws IOException {
- TreeSet<PackageId> usages = new TreeSet<PackageId>();
- for (PackageId pid: packages()) {
- try (RegisteredPackage pkg = open(pid)) {
- if (pkg == null || !pkg.isInstalled()) {
- continue;
- }
- //noinspection resource
- for (Dependency dep: pkg.getPackage().getDependencies()) {
- if (dep.matches(id)) {
- usages.add(pid);
- break;
- }
- }
- }
- }
- return usages.toArray(new PackageId[usages.size()]);
- }
-
- @Nonnull
- @Override
- public DependencyReport analyzeDependencies(@Nonnull PackageId id, boolean onlyInstalled) throws IOException, NoSuchPackageException {
- List<Dependency> unresolved = new LinkedList<Dependency>();
- List<PackageId> resolved = new LinkedList<PackageId>();
- try (RegisteredPackage pkg = open(id)) {
- if (pkg == null) {
- throw new NoSuchPackageException().setId(id);
- }
- //noinspection resource
- for (Dependency dep : pkg.getPackage().getDependencies()) {
- PackageId resolvedId = resolve(dep, onlyInstalled);
- if (resolvedId == null) {
- unresolved.add(dep);
- } else {
- resolved.add(resolvedId);
- }
- }
- }
-
- return new DependencyReportImpl(id, unresolved.toArray(new Dependency[unresolved.size()]),
- resolved.toArray(new PackageId[resolved.size()])
- );
- }
-
@Nonnull
@Override
public PackageId register(@Nonnull InputStream in, boolean replace) throws IOException, PackageExistsException {
@@ -820,40 +760,28 @@ public class JcrPackageRegistry implemen
return packRootPaths[0] + getRelativeInstallationPath(id);
}
- /**
- * Returns the relative path of this package. please note that since 2.3 this also
- * includes the version, but never the extension (.zip).
- *
- * @param id the package id
- * @return the relative path of this package
- * @since 2.2
- */
- public String getRelativeInstallationPath(PackageId id) {
- StringBuilder b = new StringBuilder("/");
- if (id.getGroup().length() > 0) {
- b.append(id.getGroup());
- b.append("/");
- }
- b.append(id.getName());
- String v = id.getVersion().toString();
- if (v.length() > 0) {
- b.append("-").append(v);
+ @Override
+ public void installPackage(@Nonnull Session session, @Nonnull RegisteredPackage pkg, @Nonnull ImportOptions opts,
+ boolean extract) throws IOException, PackageException {
+ try (JcrPackage jcrPkg = ((JcrRegisteredPackage) pkg).getJcrPackage()) {
+ if (extract) {
+ jcrPkg.extract(opts);
+ } else {
+ jcrPkg.install(opts);
+ }
+ } catch (RepositoryException e) {
+ throw new IOException(e);
}
- return b.toString();
- }
-
- /**
- * Creates a random package id for packages that lack one.
- * @return a random package id.
- */
- private static PackageId createRandomPid() {
- return new PackageId("temporary", "pack_" + UUID.randomUUID().toString(), (String) null);
}
- @Nonnull
@Override
- public ExecutionPlanBuilder createExecutionPlan() {
- return new ExecutionPlanBuilderImpl(this);
+ public void uninstallPackage(@Nonnull Session session, @Nonnull RegisteredPackage pkg, @Nonnull ImportOptions opts)
+ throws IOException, PackageException {
+ try (JcrPackage jcrPkg = ((JcrRegisteredPackage) pkg).getJcrPackage()) {
+ jcrPkg.uninstall(opts);
+ } catch (RepositoryException e) {
+ throw new IOException(e);
+ }
}
}
\ No newline at end of file
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/PackageTaskImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/PackageTaskImpl.java?rev=1836554&r1=1836553&r2=1836554&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/PackageTaskImpl.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/PackageTaskImpl.java Tue Jul 24 14:32:12 2018
@@ -20,14 +20,13 @@ import java.io.IOException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import javax.jcr.RepositoryException;
import org.apache.jackrabbit.vault.fs.io.ImportOptions;
import org.apache.jackrabbit.vault.packaging.DependencyHandling;
-import org.apache.jackrabbit.vault.packaging.JcrPackage;
import org.apache.jackrabbit.vault.packaging.NoSuchPackageException;
import org.apache.jackrabbit.vault.packaging.PackageException;
import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.registry.PackageRegistry;
import org.apache.jackrabbit.vault.packaging.registry.PackageTask;
import org.apache.jackrabbit.vault.packaging.registry.RegisteredPackage;
import org.slf4j.Logger;
@@ -152,13 +151,9 @@ public class PackageTaskImpl implements
if (pkg == null) {
throw new NoSuchPackageException("No such package: " + id);
}
- if (!(pkg instanceof JcrRegisteredPackage)) {
- throw new PackageException("non jcr packages not supported yet");
- }
- try (JcrPackage jcrPkg = ((JcrRegisteredPackage) pkg).getJcrPackage()){
- jcrPkg.uninstall(opts);
- } catch (RepositoryException e) {
- throw new IOException(e);
+ PackageRegistry registry = plan.getRegistry();
+ if (registry instanceof InternalPackageRegistry) {
+ ((InternalPackageRegistry)registry).uninstallPackage(plan.getSession(), pkg, opts);
}
}
}
@@ -179,17 +174,9 @@ public class PackageTaskImpl implements
if (pkg == null) {
throw new NoSuchPackageException("No such package: " + id);
}
- if (!(pkg instanceof JcrRegisteredPackage)) {
- throw new PackageException("non jcr packages not supported yet");
- }
- try (JcrPackage jcrPkg = ((JcrRegisteredPackage) pkg).getJcrPackage()){
- if (extract) {
- jcrPkg.extract(opts);
- } else {
- jcrPkg.install(opts);
- }
- } catch (RepositoryException e) {
- throw new IOException(e);
+ PackageRegistry registry = plan.getRegistry();
+ if (registry instanceof InternalPackageRegistry) {
+ ((InternalPackageRegistry)registry).installPackage(plan.getSession(), pkg, opts, extract);
}
}
}
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/package-info.java?rev=1836554&r1=1836553&r2=1836554&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/package-info.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/package-info.java Tue Jul 24 14:32:12 2018
@@ -14,5 +14,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@org.osgi.annotation.versioning.Version("1.0.0")
+@org.osgi.annotation.versioning.Version("1.1.0")
package org.apache.jackrabbit.vault.packaging.registry;
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java?rev=1836554&r1=1836553&r2=1836554&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java Tue Jul 24 14:32:12 2018
@@ -92,6 +92,7 @@ import org.apache.jackrabbit.vault.packa
import org.apache.jackrabbit.vault.packaging.impl.ActivityLog;
import org.apache.jackrabbit.vault.packaging.impl.JcrPackageManagerImpl;
import org.apache.jackrabbit.vault.packaging.impl.ZipVaultPackage;
+import org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry;
import org.apache.jackrabbit.vault.util.Text;
import org.junit.After;
import org.junit.AfterClass;
@@ -438,7 +439,7 @@ public class IntegrationTestBase {
*/
public String getInstallationPath(PackageId id) {
// make sure we use the one from the test parameter
- return packMgr.getRegistry().getInstallationPath(id) + ".zip";
+ return ((JcrPackageRegistry)packMgr.getRegistry()).getInstallationPath(id) + ".zip";
}
public void assertPackageNodeExists(PackageId id) throws RepositoryException {
Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestFSInstallState.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestFSInstallState.java?rev=1836554&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestFSInstallState.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestFSInstallState.java Tue Jul 24 14:32:12 2018
@@ -0,0 +1,95 @@
+/*
+ * 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.packaging.integration;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.jackrabbit.vault.packaging.Dependency;
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.SubPackageHandling;
+import org.apache.jackrabbit.vault.packaging.registry.impl.FSInstallState;
+import org.apache.jackrabbit.vault.packaging.registry.impl.FSPackageStatus;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test the Package registry interface
+ */
+public class TestFSInstallState {
+
+ private static final PackageId TMP_PACKAGE_ID = new PackageId("my_packages", "tmp", "");
+
+ private static final String TEST_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<registryMetadata packageid=\"my_packages:tmp\" installtime=\"1234\"\n" +
+ " filepath=\"test.zip\" external=\"true\" packagestatus=\"extracted\">\n" +
+ " <dependency packageid=\"my_packages:tmp\"/>\n" +
+ " <subpackage packageid=\"my_packages:tmp\" sphoption=\"ADD\"/>\n" +
+ "</registryMetadata>\n";
+
+ @Test
+ public void testWriteInstallState() throws IOException {
+ File testFile = new File("test.zip");
+ Set<Dependency> deps = new HashSet<>();
+ deps.add(new Dependency(TMP_PACKAGE_ID));
+ Map<PackageId, SubPackageHandling.Option> subs = new HashMap<>();
+ subs.put(TMP_PACKAGE_ID, SubPackageHandling.Option.ADD);
+
+ FSInstallState state = new FSInstallState(TMP_PACKAGE_ID, FSPackageStatus.EXTRACTED)
+ .withFilePath(testFile.toPath())
+ .withExternal(true)
+ .withDependencies(deps)
+ .withSubPackages(subs)
+ .withInstallTime(1234L);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ state.save(out);
+ out.close();
+
+ assertEquals(TEST_XML, out.toString("utf-8"));
+ }
+
+ @Test
+ public void testReadInstallStateNonExistent() throws IOException {
+ FSInstallState state = FSInstallState.fromFile(new File("nonexist.xml"));
+ assertEquals(null, state);
+ }
+ @Test
+ public void testReadInstallState() throws IOException {
+ Set<Dependency> deps = new HashSet<>();
+ deps.add(new Dependency(TMP_PACKAGE_ID));
+ Map<PackageId, SubPackageHandling.Option> subs = new HashMap<>();
+ subs.put(TMP_PACKAGE_ID, SubPackageHandling.Option.ADD);
+
+ FSInstallState state = FSInstallState.fromStream(new ByteArrayInputStream(TEST_XML.getBytes("utf-8")), "test.xml");
+ assertEquals(Paths.get("test.zip"), state.getFilePath());
+ assertEquals(FSPackageStatus.EXTRACTED, state.getStatus());
+ assertEquals(true, state.isExternal());
+ assertEquals(deps, state.getDependencies());
+ assertEquals(subs, state.getSubPackages());
+ assertEquals((Long) 1234L, state.getInstallationTime());
+
+ }
+}
\ No newline at end of file