001: package org.drools.scm.jcr;
002:
003: import java.io.ByteArrayOutputStream;
004: import java.io.OutputStream;
005: import java.util.ArrayList;
006: import java.util.Arrays;
007: import java.util.Collection;
008: import java.util.Collections;
009: import java.util.Comparator;
010: import java.util.Iterator;
011: import java.util.List;
012: import java.util.StringTokenizer;
013:
014: import org.drools.repository.AssetItem;
015: import org.drools.repository.PackageItem;
016: import org.drools.repository.RulesRepository;
017: import org.drools.scm.DefaultScmEntry;
018: import org.drools.scm.ScmAction;
019: import org.drools.scm.ScmActionFactory;
020: import org.drools.scm.ScmEntry;
021: import org.drools.scm.log.ScmLogEntry;
022: import org.drools.scm.log.ScmLogEntryItem;
023: import org.drools.scm.log.ScmLogEntry.Add;
024: import org.drools.scm.log.ScmLogEntry.Copy;
025: import org.drools.scm.log.ScmLogEntry.Delete;
026: import org.drools.scm.log.ScmLogEntry.Update;
027: import org.tmatesoft.svn.core.SVNNodeKind;
028:
029: public class JcrActionFactory implements ScmActionFactory {
030:
031: private RulesRepository repository;
032:
033: public JcrActionFactory(RulesRepository repo) {
034: this .repository = repo;
035: }
036:
037: public ScmAction addDirectory(String root, String path) {
038: return new AddDirectory(root, path);
039: }
040:
041: public ScmAction addFile(String path, String file, byte[] content) {
042: return new AddFile(path, file, content);
043: }
044:
045: public ScmAction copyDirectory(String path, String newPath,
046: long revision) {
047: return null;
048: }
049:
050: public ScmAction copyFile(String path, String file, String newPath,
051: String newFile, long revision) {
052: return null;
053: }
054:
055: public ScmAction deleteDirectory(String path) {
056: return null;
057: }
058:
059: public ScmAction deleteFile(String path, String file) {
060: return null;
061: }
062:
063: public void execute(ScmAction action, String message)
064: throws Exception {
065:
066: action.applyAction(new RepositoryContext(repository, message));
067: repository.save();
068: }
069:
070: public void getContent(String path, String file, long revision,
071: OutputStream os) throws Exception {
072: }
073:
074: public long getLatestRevision() throws Exception {
075: return 0;
076: }
077:
078: public List listEntries(String path) throws Exception {
079: // Build a list of packages which are for this path and all sub paths
080: List pkgs = new ArrayList();
081: String pathAsPackageName = toPackageName(path);
082: for (Iterator it = this .repository.listPackages(); it.hasNext();) {
083: PackageItem pkgItem = (PackageItem) it.next();
084: if (pkgItem.getName().startsWith(pathAsPackageName)) {
085: pkgs.add(pkgItem);
086: }
087:
088: }
089:
090: // now sort so that it's directory listing order
091: Collections.sort(pkgs, new PackagePathComparator());
092:
093: // Now iterate each directory create an ScmEntry and then add an ScmEntry for each child
094: List entries = new ArrayList();
095: String parentPath = path;
096: for (Iterator pkgIter = pkgs.iterator(); pkgIter.hasNext();) {
097: PackageItem item = (PackageItem) pkgIter.next();
098:
099: DefaultScmEntry scmEntry = new DefaultScmEntry();
100: scmEntry.setPath(parentPath);
101: String name = toDirectoryName(item.getName()).substring(
102: parentPath.length());
103: scmEntry.setName(name);
104: scmEntry.setAuthor(item.getPublisher());
105: scmEntry.setDate(item.getLastModified().getTime());
106: scmEntry.setRevision(new Long(item.getVersionNumber())
107: .longValue());
108: scmEntry.setSize(0);
109: scmEntry.setType(ScmEntry.DIRECTORY);
110: entries.add(scmEntry);
111:
112: String pkgNameAsPath = toDirectoryName(item.getName());
113: for (Iterator assetIter = item.getAssets(); assetIter
114: .hasNext();) {
115: AssetItem assetItem = (AssetItem) assetIter.next();
116:
117: if (!(assetItem.getVersionNumber() == 0)) {
118:
119: scmEntry = new DefaultScmEntry();
120: scmEntry.setPath(pkgNameAsPath);
121: scmEntry.setName(toFileName(assetItem));
122: scmEntry.setAuthor(assetItem.getPublisher());
123: scmEntry.setDate(assetItem.getLastModified()
124: .getTime());
125: scmEntry.setRevision(new Long(assetItem
126: .getVersionNumber()).longValue());
127: scmEntry.setSize(0);
128: scmEntry.setType(ScmEntry.FILE);
129: entries.add(scmEntry);
130: }
131: }
132: }
133:
134: return entries;
135: }
136:
137: public static class PackagePathComparator implements Comparator {
138: public int compare(Object object0, Object object1) {
139: PackageItem item0 = (PackageItem) object0;
140: PackageItem item1 = (PackageItem) object1;
141:
142: return item0.getName().compareTo(item1.getName());
143: }
144: }
145:
146: public ScmAction moveDirectory(String path, String newPath,
147: long revision) {
148: return null;
149: }
150:
151: public ScmAction moveFile(String path, String file, String newPath,
152: String newFile, long revision) {
153: return null;
154: }
155:
156: public ScmAction updateFile(String path, String file,
157: byte[] oldContent, byte[] newContent) {
158: return new UpdateFile(path, file, oldContent, newContent);
159: }
160:
161: public void syncToScmLog(List list, ScmActionFactory factory)
162: throws Exception {
163: for (Iterator it = list.iterator(); it.hasNext();) {
164: ScmLogEntry entry = (ScmLogEntry) it.next();
165: for (Iterator it2 = entry.getAction().iterator(); it
166: .hasNext();) {
167: ScmLogEntryItem item = (ScmLogEntryItem) it2.next();
168: ScmAction action;
169: switch (item.getActionType()) {
170: case 'A': {
171: Add add = (Add) item;
172: if (add.getPathType() == 'D') {
173: addDirectory("", add.getPath());
174: } else {
175: int lastSlash = add.getPath().lastIndexOf('/');
176: String path = add.getPath().substring(0,
177: lastSlash - 1);
178: String file = add.getPath().substring(
179: lastSlash + 1,
180: add.getPath().length() - 1);
181:
182: ByteArrayOutputStream bos = new ByteArrayOutputStream();
183: factory.getContent(path, file, -1, bos);
184: action = addFile(path, file, bos.toByteArray());
185: }
186: break;
187: }
188: case 'C': {
189: Copy copy = (Copy) item;
190: if (copy.getPathType() == 'D') {
191: action = copyDirectory(copy.getFromPath(), copy
192: .getToPath(), copy.getFromRevision());
193: } else {
194: int lastSlash = copy.getFromPath().lastIndexOf(
195: '/');
196: String fromPath = copy.getFromPath().substring(
197: 0, lastSlash - 1);
198: String fromFile = copy.getFromPath().substring(
199: lastSlash + 1,
200: copy.getFromPath().length() - 1);
201:
202: lastSlash = copy.getToPath().lastIndexOf('/');
203: String toPath = copy.getToPath().substring(0,
204: lastSlash - 1);
205: String toFile = copy.getToPath().substring(
206: lastSlash + 1,
207: copy.getToPath().length() - 1);
208: action = copyFile(fromPath, fromFile, toPath,
209: toFile, copy.getFromRevision());
210: }
211:
212: break;
213: }
214: case 'D': {
215: Delete delete = (Delete) item;
216: if (delete.getPathType() == 'D') {
217: action = deleteDirectory(delete.getPath());
218: } else {
219: int lastSlash = delete.getPath().lastIndexOf(
220: '/');
221: String path = delete.getPath().substring(0,
222: lastSlash - 1);
223: String file = delete.getPath().substring(
224: lastSlash + 1,
225: delete.getPath().length() - 1);
226:
227: action = deleteFile(path, file);
228: }
229: break;
230: }
231: case 'U':
232: // Can only be a file
233: Update update = (Update) item;
234: int lastSlash = update.getPath().lastIndexOf('/');
235: String path = update.getPath().substring(0,
236: lastSlash - 1);
237: String file = update.getPath().substring(
238: lastSlash + 1,
239: update.getPath().length() - 1);
240:
241: ByteArrayOutputStream bosOriginal = new ByteArrayOutputStream();
242: getContent(path, file, -1, bosOriginal);
243:
244: ByteArrayOutputStream bosNew = new ByteArrayOutputStream();
245: factory.getContent(path, file,
246: update.getRevision(), bosNew);
247:
248: action = updateFile(path, file, bosOriginal
249: .toByteArray(), bosNew.toByteArray());
250:
251: break;
252: case 'R':
253: // @TODO this is a delete and add
254: break;
255: }
256:
257: }
258: }
259: }
260:
261: public static class AddFile implements ScmAction {
262: private String file;
263: private String path;
264: private byte[] content;
265:
266: public AddFile(String path, String file, byte[] content) {
267: this .path = path;
268: this .file = file;
269: this .content = content;
270: }
271:
272: public void applyAction(Object context) throws Exception {
273: RepositoryContext ctx = (RepositoryContext) context;
274:
275: PackageItem pkg = ctx.repository
276: .loadPackage(toPackageName(path));
277:
278: StringTokenizer tk = new StringTokenizer(file, ".");
279:
280: String name = tk.nextToken();
281: String format = tk.nextToken();
282:
283: AssetItem asset = pkg.addAsset(name, ctx.message);
284: asset.updateFormat(format);
285: asset.updateContent(new String(content));
286: }
287: }
288:
289: /**
290: * root should be the last, previously created, parent folder. Each directory in the path
291: * will be created.
292: *
293: */
294: public static class AddDirectory implements ScmAction {
295: private String root;
296: private String path;
297:
298: public AddDirectory(String root, String path) {
299: this .root = root;
300: this .path = path;
301: }
302:
303: public void applyAction(Object context) throws Exception {
304: RepositoryContext ctx = (RepositoryContext) context;
305:
306: if (!this .root.equals("")) {
307: PackageItem pkgItem = ctx.repository
308: .loadPackage(toPackageName(this .root));
309: if (pkgItem == null) {
310: throw new RuntimeException("The parent package '"
311: + this .root + "' must exist");
312: }
313: }
314:
315: PackageItem item = ctx.repository.createPackage(
316: toPackageName(root + "/" + this .path),
317: "initial package");
318: //item.checkin( "save" );
319: }
320: }
321:
322: public static class UpdateFile implements ScmAction {
323: private String file;
324: private String path;
325: private byte[] oldContent;
326: private byte[] newContent;
327:
328: public UpdateFile(String path, String file, byte[] oldContent,
329: byte[] newContent) {
330: this .path = path;
331: this .file = file;
332: this .oldContent = oldContent;
333: this .newContent = newContent;
334: }
335:
336: public void applyAction(Object context) throws Exception {
337: RepositoryContext ctx = (RepositoryContext) context;
338: PackageItem pkg = ctx.repository
339: .loadPackage(toPackageName(path));
340: String name = file.substring(0, file.indexOf('.'));
341: AssetItem asset = pkg.loadAsset(name);
342: asset.updateContent(new String(newContent));
343: asset.checkin(ctx.message);
344: }
345: }
346:
347: public static class CopyFile implements ScmAction {
348: private String file;
349: private String path;
350: private String newPath;
351: private String newFile;
352: private long revision;
353:
354: public CopyFile(String path, String file, String newPath,
355: String newFile, long revision) {
356: this .path = path;
357: this .file = file;
358: this .newPath = newPath;
359: this .newFile = newFile;
360: this .revision = revision;
361: }
362:
363: public void applyAction(Object context) throws Exception {
364:
365: }
366: }
367:
368: public static class CopyDirectory implements ScmAction {
369: private String path;
370: private String newPath;
371: private long revision;
372:
373: public CopyDirectory(String path, String newPath, long revision) {
374: this .path = path;
375: this .newPath = newPath;
376: this .revision = revision;
377: }
378:
379: public void applyAction(Object context) throws Exception {
380: }
381: }
382:
383: public static class MoveFile implements ScmAction {
384: private String file;
385: private String path;
386: private String newPath;
387: private String newFile;
388: private long revision;
389:
390: public MoveFile(String path, String file, String newPath,
391: String newFile, long revision) {
392: this .path = path;
393: this .file = file;
394: this .newPath = newPath;
395: this .newFile = newFile;
396: this .revision = revision;
397: }
398:
399: public void applyAction(Object context) throws Exception {
400: }
401: }
402:
403: public static class MoveDirectory implements ScmAction {
404: private String path;
405: private String newPath;
406: private long revision;
407:
408: public MoveDirectory(String path, String newPath, long revision) {
409: this .path = path;
410: this .newPath = newPath;
411: this .revision = revision;
412: }
413:
414: public void applyAction(Object context) throws Exception {
415:
416: }
417: }
418:
419: public static class DeleteFile implements ScmAction {
420: private String path;
421: private String file;
422:
423: public DeleteFile(String path, String file) {
424: this .path = path;
425: this .file = file;
426: }
427:
428: public void applyAction(Object context) throws Exception {
429: }
430: }
431:
432: public static class DeleteDirectory implements ScmAction {
433: private String path;
434:
435: public DeleteDirectory(String path) {
436: this .path = path;
437: }
438:
439: public void applyAction(Object context) throws Exception {
440: }
441: }
442:
443: /**
444: * This is used for passing in a context to perform the actions.
445: */
446: public static class RepositoryContext {
447:
448: public RepositoryContext(RulesRepository repository2,
449: String message2) {
450: this .repository = repository2;
451: this .message = message2;
452: }
453:
454: public RulesRepository repository;
455: public String message;
456: }
457:
458: private static String convertPath(String path, String token,
459: String replace) {
460: if (path.indexOf(token) == -1)
461: return path;
462: StringTokenizer tk = new StringTokenizer(path, token);
463: StringBuffer buf = new StringBuffer();
464: while (tk.hasMoreTokens()) {
465: String el = tk.nextToken();
466: buf.append(el);
467: if (tk.hasMoreTokens())
468: buf.append(replace);
469: }
470: return buf.toString();
471: }
472:
473: static String toDirectoryName(String packageName) {
474: return convertPath(packageName, ".", "/");
475: }
476:
477: static String toPackageName(String directory) {
478: return convertPath(directory, "/", ".");
479: }
480:
481: static String toFileName(AssetItem item) {
482: return item.getName() + "." + item.getFormat();
483: }
484:
485: }
|