View Javadoc
1   package org.argeo.cli.jcr;
2   
3   import java.net.URI;
4   import java.net.URISyntaxException;
5   import java.nio.file.Paths;
6   import java.util.HashMap;
7   import java.util.List;
8   import java.util.Map;
9   
10  import javax.jcr.Credentials;
11  import javax.jcr.Node;
12  import javax.jcr.Repository;
13  import javax.jcr.RepositoryException;
14  import javax.jcr.RepositoryFactory;
15  import javax.jcr.Session;
16  import javax.jcr.SimpleCredentials;
17  
18  import org.apache.commons.cli.CommandLine;
19  import org.apache.commons.cli.Option;
20  import org.apache.commons.cli.Options;
21  import org.apache.jackrabbit.core.RepositoryImpl;
22  import org.apache.jackrabbit.core.config.RepositoryConfig;
23  import org.argeo.cli.CommandArgsException;
24  import org.argeo.cli.CommandRuntimeException;
25  import org.argeo.cli.DescribedCommand;
26  import org.argeo.jackrabbit.client.ClientDavexRepositoryFactory;
27  import org.argeo.jcr.JcrUtils;
28  import org.argeo.sync.SyncResult;
29  
30  public class JcrSync implements DescribedCommand<SyncResult<Node>> {
31  	public final static String DEFAULT_LOCALFS_CONFIG = "repository-localfs.xml";
32  
33  	final static Option deleteOption = Option.builder().longOpt("delete").desc("delete from target").build();
34  	final static Option recursiveOption = Option.builder("r").longOpt("recursive").desc("recurse into directories")
35  			.build();
36  	final static Option progressOption = Option.builder().longOpt("progress").hasArg(false).desc("show progress")
37  			.build();
38  
39  	@Override
40  	public SyncResult<Node> apply(List<String> t) {
41  		try {
42  			CommandLine line = toCommandLine(t);
43  			List<String> remaining = line.getArgList();
44  			if (remaining.size() == 0) {
45  				throw new CommandArgsException("There must be at least one argument");
46  			}
47  			URI sourceUri = new URI(remaining.get(0));
48  			URI targetUri;
49  			if (remaining.size() == 1) {
50  				targetUri = Paths.get(System.getProperty("user.dir")).toUri();
51  			} else {
52  				targetUri = new URI(remaining.get(1));
53  			}
54  			boolean delete = line.hasOption(deleteOption.getLongOpt());
55  			boolean recursive = line.hasOption(recursiveOption.getLongOpt());
56  
57  			// TODO make it configurable
58  			String sourceWorkspace = "home";
59  			String targetWorkspace = sourceWorkspace;
60  
61  			final Repository sourceRepository;
62  			final Session sourceSession;
63  			Credentials sourceCredentials = null;
64  			final Repository targetRepository;
65  			final Session targetSession;
66  			Credentials targetCredentials = null;
67  
68  			if ("http".equals(sourceUri.getScheme()) || "https".equals(sourceUri.getScheme())) {
69  				sourceRepository = createRemoteRepository(sourceUri);
70  			} else if (null == sourceUri.getScheme() || "file".equals(sourceUri.getScheme())) {
71  				RepositoryConfig repositoryConfig = RepositoryConfig.create(
72  						JcrSync.class.getResourceAsStream(DEFAULT_LOCALFS_CONFIG), sourceUri.getPath().toString());
73  				sourceRepository = RepositoryImpl.create(repositoryConfig);
74  				sourceCredentials = new SimpleCredentials("admin", "admin".toCharArray());
75  			} else {
76  				throw new IllegalArgumentException("Unsupported scheme " + sourceUri.getScheme());
77  			}
78  			sourceSession = JcrUtils.loginOrCreateWorkspace(sourceRepository, sourceWorkspace, sourceCredentials);
79  
80  			if ("http".equals(targetUri.getScheme()) || "https".equals(targetUri.getScheme())) {
81  				targetRepository = createRemoteRepository(targetUri);
82  			} else if (null == targetUri.getScheme() || "file".equals(targetUri.getScheme())) {
83  				RepositoryConfig repositoryConfig = RepositoryConfig.create(
84  						JcrSync.class.getResourceAsStream(DEFAULT_LOCALFS_CONFIG), targetUri.getPath().toString());
85  				targetRepository = RepositoryImpl.create(repositoryConfig);
86  				targetCredentials = new SimpleCredentials("admin", "admin".toCharArray());
87  			} else {
88  				throw new IllegalArgumentException("Unsupported scheme " + targetUri.getScheme());
89  			}
90  			targetSession = JcrUtils.loginOrCreateWorkspace(targetRepository, targetWorkspace, targetCredentials);
91  
92  			JcrUtils.copy(sourceSession.getRootNode(), targetSession.getRootNode());
93  			return new SyncResult<Node>();
94  		} catch (URISyntaxException e) {
95  			throw new CommandArgsException(e);
96  		} catch (Exception e) {
97  			throw new CommandRuntimeException(e, this, t);
98  		}
99  	}
100 
101 	protected Repository createRemoteRepository(URI uri) throws RepositoryException {
102 		RepositoryFactory repositoryFactory = new ClientDavexRepositoryFactory();
103 		Map<String, String> params = new HashMap<String, String>();
104 		params.put(ClientDavexRepositoryFactory.JACKRABBIT_DAVEX_URI, uri.toString());
105 		params.put(ClientDavexRepositoryFactory.JACKRABBIT_REMOTE_DEFAULT_WORKSPACE, "main");
106 		return repositoryFactory.getRepository(params);
107 	}
108 
109 	@Override
110 	public Options getOptions() {
111 		Options options = new Options();
112 		options.addOption(recursiveOption);
113 		options.addOption(deleteOption);
114 		options.addOption(progressOption);
115 		return options;
116 	}
117 
118 	@Override
119 	public String getUsage() {
120 		return "[source URI] [target URI]";
121 	}
122 
123 	public static void main(String[] args) {
124 		DescribedCommand.mainImpl(new JcrSync(), args);
125 	}
126 
127 	@Override
128 	public String getDescription() {
129 		return "Synchronises JCR repositories";
130 	}
131 
132 }