You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:46:33 UTC
[sling-org-apache-sling-jcr-classloader] 13/18: Experimental class
loader writer for scripting engines.
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to annotated tag org.apache.sling.jcr.classloader-2.0.6
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-classloader.git
commit dea3efa0d3e719414e6af10c0f7ed5a0836c2f0b
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Fri Jul 17 06:16:52 2009 +0000
Experimental class loader writer for scripting engines.
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/jcr/classloader@794977 13f79535-47bb-0310-9956-ffa450edef68
---
pom.xml | 5 +
.../internal/RepositoryClassLoaderFacade.java | 31 +--
.../RepositoryClassLoaderProviderImpl.java | 308 ++++++++++++++++++++-
3 files changed, 302 insertions(+), 42 deletions(-)
diff --git a/pom.xml b/pom.xml
index a36fceb..539ba29 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,11 @@
<version>0.9.0-SNAPSHOT</version>
</dependency>
<dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.mime</artifactId>
+ <version>2.1.0-incubator</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-classloader</artifactId>
<version>1.4.1</version>
diff --git a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderFacade.java b/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderFacade.java
index cc5ff1a..9324105 100644
--- a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderFacade.java
+++ b/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderFacade.java
@@ -47,15 +47,6 @@ class RepositoryClassLoaderFacade extends URLClassLoader {
private String[] classPath;
private DynamicRepositoryClassLoader delegate;
- /**
- * The reference counter. If not greater than zero, there are this
- * number of (assumed) life references.
- *
- * @see #ref()
- * @see #deref()
- */
- private int refCtr = 0;
-
public RepositoryClassLoaderFacade(
RepositoryClassLoaderProviderImpl classLoaderProvider,
ClassLoader parent,
@@ -140,27 +131,6 @@ class RepositoryClassLoaderFacade extends URLClassLoader {
}
}
- /**
- * Increases the reference counter of this class loader.
- */
- /* package */void ref() {
- this.refCtr++;
- }
-
- /**
- * Decreases the reference counter of this class loader and calls the
- * base class <code>destroy()</code> method, if this class loader has
- * already been destroyed by calling the {@link #destroy()} method.
- */
- /* package */void deref() {
- this.refCtr--;
-
- // destroy if the loader should be destroyed and no refs exist
-// if (refCtr <= 0 /* && destroyed */ ) {
-// destroy();
-// }
- }
-
//---------- internal -----------------------------------------------------
private Session getSession() throws RepositoryException {
@@ -197,4 +167,5 @@ class RepositoryClassLoaderFacade extends URLClassLoader {
return this.delegate;
}
+
}
diff --git a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderProviderImpl.java b/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderProviderImpl.java
index af5ee61..425c9b5 100644
--- a/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderProviderImpl.java
+++ b/src/main/java/org/apache/sling/jcr/classloader/internal/RepositoryClassLoaderProviderImpl.java
@@ -18,20 +18,33 @@
*/
package org.apache.sling.jcr.classloader.internal;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.Dictionary;
import java.util.Iterator;
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import org.apache.commons.collections.BidiMap;
import org.apache.commons.collections.bidimap.DualHashBidiMap;
+import org.apache.sling.commons.classloader.ClassLoaderWriter;
import org.apache.sling.commons.classloader.DynamicClassLoaderProvider;
+import org.apache.sling.commons.mime.MimeTypeService;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.classloader.RepositoryClassLoaderProvider;
import org.osgi.framework.Bundle;
import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* The <code>RepositoryClassLoaderProviderImpl</code> TODO
@@ -44,7 +57,10 @@ import org.osgi.service.component.ComponentContext;
* @scr.service servicefactory="true"
*/
public class RepositoryClassLoaderProviderImpl
- implements RepositoryClassLoaderProvider, DynamicClassLoaderProvider {
+ implements RepositoryClassLoaderProvider, DynamicClassLoaderProvider, ClassLoaderWriter {
+
+ /** default log */
+ private static final Logger log = LoggerFactory.getLogger(RepositoryClassLoaderFacade.class);
/**
* @scr.property values0="/var/classes"
@@ -74,6 +90,9 @@ public class RepositoryClassLoaderProviderImpl
private BundleProxyClassLoader parent;
+ /** @scr.reference policy="dynamic" */
+ private MimeTypeService mimeTypeService;
+
public ClassLoader getClassLoader(String owner) {
String classLoaderOwner = this.getClassLoaderOwner(owner);
RepositoryClassLoaderFacade loader =
@@ -84,17 +103,11 @@ public class RepositoryClassLoaderProviderImpl
this.loaders.put(classLoaderOwner, loader);
}
- // extend reference counter
- loader.ref();
-
return loader;
}
public void ungetClassLoader(ClassLoader classLoader) {
- if (classLoader instanceof RepositoryClassLoaderFacade) {
- RepositoryClassLoaderFacade cl = (RepositoryClassLoaderFacade) classLoader;
- cl.deref();
- }
+ // nothing to do
}
//---------- Support for RepositoryClassLoaderFacade ----------------------
@@ -126,18 +139,289 @@ public class RepositoryClassLoaderProviderImpl
(RepositoryClassLoaderFacade) this.loaders.get(classLoaderOwner);
if (loader == null) {
loader = new RepositoryClassLoaderFacade(this, parent,
- OWNER_DEFAULT, this.classPath);
+ this.classLoaderOwner, this.classPath);
this.loaders.put(classLoaderOwner, loader);
}
- // extend reference counter
- loader.ref();
-
return loader;
}
//---------- SCR Integration ----------------------------------------------
+ /**
+ * @see org.apache.sling.commons.classloader.ClassLoaderWriter#delete(java.lang.String)
+ */
+ public boolean delete(String name) {
+ name = cleanPath(name);
+ Node parentNode = null;
+ Session session = null;
+ try {
+ session = getSession(this.classLoaderOwner);
+ if (session.itemExists(name)) {
+ Item fileItem = session.getItem(name);
+ parentNode = fileItem.getParent();
+ fileItem.remove();
+ parentNode.save();
+ return true;
+ }
+ } catch (RepositoryException re) {
+ log.error("Cannot remove " + name, re);
+ } finally {
+ checkNode(parentNode, name);
+ if ( session != null ) {
+ session.logout();
+ }
+ }
+
+ // fall back to false if item does not exist or in case of error
+ return false;
+ }
+
+ /**
+ * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getOutputStream(java.lang.String)
+ */
+ public OutputStream getOutputStream(String name) {
+ final String path = cleanPath(name);
+ return new RepositoryOutputStream(this, path);
+ }
+
+ /**
+ * @see org.apache.sling.commons.classloader.ClassLoaderWriter#rename(java.lang.String, java.lang.String)
+ */
+ public boolean rename(String oldName, String newName) {
+ Session session = null;
+ try {
+ oldName = cleanPath(oldName);
+ newName = cleanPath(newName);
+
+ session = this.getSession(this.classLoaderOwner);
+ session.getWorkspace().move(oldName, newName);
+ return true;
+ } catch (RepositoryException re) {
+ log.error("Cannot rename " + oldName + " to " + newName, re);
+ } finally {
+ if ( session != null ) {
+ session.logout();
+ }
+ }
+
+ // fallback to false in case of error or non-existence of oldFileName
+ return false;
+ }
+
+ /**
+ * Creates a folder hierarchy in the repository.
+ */
+ private boolean mkdirs(final Session session, String path) {
+ Node parentNode = null;
+ try {
+ // quick test
+ if (session.itemExists(path) && session.getItem(path).isNode()) {
+ return true;
+ }
+
+ // check path walking it down
+ Node current = session.getRootNode();
+ String[] names = path.split("/");
+ for (int i = 0; i < names.length; i++) {
+ if (names[i] == null || names[i].length() == 0) {
+ continue;
+ } else if (current.hasNode(names[i])) {
+ current = current.getNode(names[i]);
+ } else {
+ if (parentNode == null) {
+ parentNode = current;
+ }
+ current = current.addNode(names[i], "nt:folder");
+ }
+ }
+
+ if (parentNode != null) {
+ parentNode.save();
+ return true;
+ }
+
+ } catch (RepositoryException re) {
+ log.error("Cannot create folder path " + path, re);
+ } finally {
+ checkNode(parentNode, path);
+ }
+
+ // false in case of error or no need to create
+ return false;
+ }
+
+ private static void checkNode(Node node, String path) {
+ if (node != null && node.isModified()) {
+ try {
+ node.refresh(false);
+ } catch (RepositoryException re) {
+ log.error("Cannot refresh node for " + path
+ + " after failed save", re);
+ }
+ }
+ }
+
+ private String cleanPath(String path) {
+ // replace backslash by slash
+ path = path.replace('\\', '/');
+
+ // cut off trailing slash
+ while (path.endsWith("/")) {
+ path = path.substring(0, path.length() - 1);
+ }
+
+ if ( this.classPath == null || this.classPath.length == 0 ) {
+ return path;
+ }
+ return this.classPath[0] + path;
+ }
+
+ private static class RepositoryOutputStream extends ByteArrayOutputStream {
+
+ private final RepositoryClassLoaderProviderImpl repositoryOutputProvider;
+
+ private final String fileName;
+
+ RepositoryOutputStream(RepositoryClassLoaderProviderImpl repositoryOutputProvider,
+ String fileName) {
+ this.repositoryOutputProvider = repositoryOutputProvider;
+ this.fileName = fileName;
+ }
+
+ public void close() throws IOException {
+ super.close();
+
+ Node parentNode = null;
+ Session session = null;
+ try {
+ session = repositoryOutputProvider.getSession(repositoryOutputProvider.classLoaderOwner);
+ final int lastPos = fileName.lastIndexOf('/');
+ if ( lastPos != -1 ) {
+ repositoryOutputProvider.mkdirs(session, fileName.substring(0, lastPos));
+ }
+ Node fileNode = null;
+ Node contentNode = null;
+ if (session.itemExists(fileName)) {
+ Item item = session.getItem(fileName);
+ if (item.isNode()) {
+ Node node = item.isNode()
+ ? (Node) item
+ : item.getParent();
+ if ("jcr:content".equals(node.getName())) {
+ // replace the content properties of the jcr:content
+ // node
+ parentNode = node;
+ contentNode = node;
+ } else if (node.isNodeType("nt:file")) {
+ // try to set the content properties of jcr:content
+ // node
+ parentNode = node;
+ contentNode = node.getNode("jcr:content");
+ } else { // fileName is a node
+ // try to set the content properties of the node
+ parentNode = node;
+ contentNode = node;
+ }
+ } else {
+ // replace property with an nt:file node (if possible)
+ parentNode = item.getParent();
+ String name = item.getName();
+ fileNode = parentNode.addNode(name, "nt:file");
+ item.remove();
+ }
+ } else {
+ int lastSlash = fileName.lastIndexOf('/');
+ if (lastSlash <= 0) {
+ parentNode = session.getRootNode();
+ } else {
+ Item parent = session.getItem(fileName.substring(0,
+ lastSlash));
+ if (!parent.isNode()) {
+ // TODO: fail
+ }
+ parentNode = (Node) parent;
+ }
+ String name = fileName.substring(lastSlash + 1);
+ fileNode = parentNode.addNode(name, "nt:file");
+ }
+
+ // if we have a file node, create the contentNode
+ if (fileNode != null) {
+ contentNode = fileNode.addNode("jcr:content", "nt:resource");
+ }
+
+ final MimeTypeService mtService = this.repositoryOutputProvider.mimeTypeService;
+
+ String mimeType = (mtService == null ? null : mtService.getMimeType(fileName));
+ if (mimeType == null) {
+ mimeType = "application/octet-stream";
+ }
+
+ contentNode.setProperty("jcr:lastModified",
+ System.currentTimeMillis());
+ contentNode.setProperty("jcr:data", new ByteArrayInputStream(
+ buf, 0, size()));
+ contentNode.setProperty("jcr:mimeType", mimeType);
+
+ parentNode.save();
+ } catch (RepositoryException re) {
+ log.error("Cannot write file " + fileName, re);
+ throw new IOException("Cannot write file " + fileName
+ + ", reason: " + re.toString());
+ } finally {
+ checkNode(parentNode, fileName);
+ if ( session != null ) {
+ session.logout();
+ }
+ }
+ }
+ }
+
+ /**
+ * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getInputStream(java.lang.String)
+ */
+ public InputStream getInputStream(String fileName)
+ throws IOException {
+ final String path = cleanPath(fileName) + "/jcr:content/jcr:data";
+ Session session = null;
+ try {
+ session = getSession(this.classLoaderOwner);
+ if ( session.itemExists(path) ) {
+ final Property prop = (Property)session.getItem(path);
+ return prop.getStream();
+ }
+ throw new FileNotFoundException("Unable to find " + fileName);
+ } catch (RepositoryException re) {
+ throw (IOException) new IOException(
+ "Failed to get InputStream for " + fileName).initCause(re);
+ } finally {
+ if ( session != null ) {
+ session.logout();
+ }
+ }
+ }
+
+ /**
+ * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getLastModified(java.lang.String)
+ */
+ public long getLastModified(String fileName) {
+ final String path = cleanPath(fileName) + "/jcr:content/jcr:lastModifed";
+ Session session = null;
+ try {
+ session = getSession(this.classLoaderOwner);
+ if ( session.itemExists(path) ) {
+ final Property prop = (Property)session.getItem(path);
+ return prop.getLong();
+ }
+ } catch (RepositoryException se) {
+ log.error("Cannot get last modification time for " + fileName, se);
+ }
+
+ // fallback to "non-existant" in case of problems
+ return -1;
+ }
+
protected void activate(ComponentContext componentContext) {
@SuppressWarnings("unchecked")
Dictionary properties = componentContext.getProperties();
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.