1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module.groovy.support.classes;
35
36 import info.magnolia.context.Context;
37 import info.magnolia.jcr.util.NodeTypes;
38 import info.magnolia.jcr.util.PropertyUtil;
39
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.net.MalformedURLException;
43 import java.net.URL;
44 import java.net.URLConnection;
45 import java.net.URLStreamHandler;
46 import java.util.Calendar;
47
48 import javax.inject.Provider;
49 import javax.jcr.Node;
50 import javax.jcr.RepositoryException;
51 import javax.jcr.Session;
52
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 import groovy.lang.GroovyResourceLoader;
57
58
59
60
61
62
63
64 class MgnlGroovyResourceLoader implements GroovyResourceLoader {
65
66 private static final Logger log = LoggerFactory.getLogger(MgnlGroovyResourceLoader.class);
67 private static final String PROTOCOL = "magnolia-repository://";
68
69 private final GroovyResourceLoader delegate;
70 private final Provider<Context> provider;
71 private final String workspaceName;
72
73 MgnlGroovyResourceLoader(GroovyResourceLoader delegate, Provider<Context> provider, String workspaceName) {
74 this.delegate = delegate;
75 this.provider = provider;
76 this.workspaceName = workspaceName;
77 }
78
79
80
81
82 @Deprecated
83 MgnlGroovyResourceLoader(GroovyResourceLoader delegate, Context context, String repoName) throws UnsupportedOperationException {
84 throw new UnsupportedOperationException();
85 }
86
87 @Override
88 public URL loadGroovySource(String name) throws MalformedURLException {
89 final URL url = loadGroovySourceFromRepository(name);
90 if (url == null) {
91 return delegate.loadGroovySource(name);
92 }
93 return url;
94 }
95
96
97
98
99
100 private URL loadGroovySourceFromRepository(String name) throws MalformedURLException {
101 if (name.startsWith("[") || name.contains("$")) {
102
103
104 log.debug("Skipping {}, array or nested class.", name);
105 return null;
106 }
107
108 final String path = "/" + name.replace('.', '/');
109 try {
110 final Session session = provider.get().getJCRSession(workspaceName);
111 if (!session.nodeExists(path)) {
112 return null;
113 }
114 final Node node = session.getNode(path);
115 if (NodeTypes.Deleted.getDeleted(node) == null && PropertyUtil.getBoolean(node, "enabled", false)) {
116 return new URL(null, PROTOCOL + session.getWorkspace().getName() + path, new MagnoliaStreamHandler(session));
117 } else {
118 return null;
119 }
120 } catch (RepositoryException e) {
121 return null;
122 }
123 }
124
125
126
127
128 protected static class MagnoliaStreamHandler extends URLStreamHandler {
129 private final Session session;
130
131 public MagnoliaStreamHandler(Session session) {
132 this.session = session;
133 }
134
135 @Override
136 protected URLConnection openConnection(URL u) throws IOException {
137 if (!"magnolia-repository".equals(u.getProtocol())) {
138 throw new IllegalStateException("Unsupported protocol: " + u.getProtocol() + " (only supports \"magnolia-repository\")");
139 }
140 return new MagnoliaURLConnection(u, session);
141 }
142 }
143
144
145
146
147 protected static class MagnoliaURLConnection extends URLConnection {
148 private final Node node;
149
150 public MagnoliaURLConnection(URL u, Session session) throws IOException {
151 super(u);
152
153 final String path = u.getPath();
154
155 try {
156 this.node = session.getNode(path);
157 } catch (RepositoryException e) {
158 throw new IOException("Can't get " + path + " from the " + session.getWorkspace().getName() + " workspace: " + e.getClass().getSimpleName() + ": " + e.getMessage());
159 }
160 }
161
162 @Override
163 public void connect() throws IOException {
164
165
166
167
168
169 }
170
171 @Override
172 public InputStream getInputStream() throws IOException {
173
174 try {
175 return node.getProperty("text").getBinary().getStream();
176 } catch (RepositoryException e) {
177 throw new IOException(e);
178 }
179 }
180
181 @Override
182 public long getLastModified() {
183 try {
184 Calendar date = NodeTypes.LastModified.getLastModified(node);
185 return date.getTimeInMillis();
186 } catch (RepositoryException e) {
187 return 0;
188 }
189
190 }
191 }
192 }